4 28 省選模擬賽 負環 倍增 矩陣乘法 dp

2022-02-04 21:29:27 字數 1409 閱讀 2896

容易想到 這個環一定是簡單環。

考慮如果是複雜環 那麼顯然對於其中的第乙個簡單環來說 要麼其權值為負 如果為正沒必要走一圈 走一部分即可。

對於前者 顯然可以找到更小的 對於第二部分是遞迴定義的。

綜上 這個環是乙個簡單環。

那麼最多有n個點。

考慮列舉起點 然後 設f[i][j][k]表示從i到j經過k條邊的最短路。

容易發現最終的答案為 f[i][i][w]<0 w.

不過這樣做是n^4的。

考慮優化 容易想到二分 而上述狀態其實本質上是乙個矩陣乘法。

那麼我們可以矩陣乘法在n^3logn的時間內得到二分出答案的矩陣。

但是這樣正確性有點問題。考慮二分的答案並沒有一定的單調性。

乙個負環大小可能為3 長度為4時可能沒有負環。

更改狀態比較好 設f[i][j][k]表示從i到j <=k條邊的最短路

這樣負環就可以被我們保留下來了 關於這個轉移 乙個比較大膽的想法是 每次矩陣乘法之後對原矩陣取min.

看起來毫無道理 但是 容易發現這個取min操作相當於 做矩陣乘法時 對角線的值全部為0.

至此我們得到了乙個普通意義 即 自己到自己有乙個0條邊的東西。

如果我們要求的答案為mid 那麼顯然 mid可以由兩個小於mid的最短路組成。

從最優性來看這顯然存在。所以這樣做是正確的。

不過還需要優化複雜度。

考慮倍增出答案。預處理出矩陣即可。

複雜度n^3log.

const int maxn=310,g=3;

int n,m,maxx,ans;

int b[maxn][maxn],c[maxn][maxn];

int a[12][maxn][maxn];

int main()

rep(1,n,i)a[0][i][i]=0,b[i][i]=0;

maxx=9;

rep(1,maxx,w) }

int flag=0;

rep(1,n,i)if(a[maxx][i][i]<0)flag=1;

if(!flag)

fep(maxx,0,w)

flag=0;

rep(1,n,i)if(c[i][i]<0)

if(flag)continue;

rep(1,n,i)rep(1,n,j)b[i][j]=c[i][j];

ans=ans|(1<

} put(ans+1);

return 0;

}

省選模擬賽 環

分析 不算太難的一道題.如果把每個編號i看作乙個點,i向ai連邊,那麼最後一定會出現環,並且環與環之間是不相交的.那麼我們可以dfs預處理出所有的環,用詢問的m除以環的長度,剩下的餘數就可以o 1 計算了,時間複雜度o n 上面這種做法在處理餘數部分時比較容易寫錯.一種不容易寫錯的方法是倍增.複雜度...

省選模擬賽 project

最小割問題。建如下邊 s,i,ai 代表選用a語言編寫第i個專案 i,t,bi 代表選用a語言編寫第i個專案 其後注意要反向連邊 i,j,d 代表選用b語言編寫第i個專案,選用a語言編寫第j個專案 j,i,c 代表選用a語言編寫第i個專案,選用b語言編寫第j個專案 litc學長出的題,引文最小割題目...

mirror 省選模擬賽

標籤 狀壓dp 結論 當最優情況下,每行每列鏡子的個數都為偶數 題目可以轉化為擺放鏡子,使得格仔中產生的光環最長 所以不需要考慮鏡子到底放什麼方向 於是我們直接狀壓一列鏡子當前的奇偶性進行轉移 時間複雜度o 4n n m2 o 4 n n m2 include include include inc...