日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

bzoj2561 最小生成树

發(fā)布時(shí)間:2023/12/19 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bzoj2561 最小生成树 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題意:給你無(wú)向圖,給定一條邊,求至少在原圖中刪去多少邊才能使它同時(shí)在某個(gè)最大生成樹(shù)和某個(gè)最小生成樹(shù)中。

解:

假裝我們把邊排序了,然后把所有邊權(quán)小于給定邊的邊都加進(jìn)去了。

那么我們要?jiǎng)h的就是s到t的一個(gè)割。

最大同理。

然后我們做兩遍最小割即可。

注意邊權(quán)與給定邊相等的邊直接忽略。

1 #include <cstdio> 2 #include <algorithm> 3 #include <queue> 4 #include <cstring> 5 6 const int N = 20010, M = 1000010, INF = 0x3f3f3f3f; 7 const int dx[] = {1, 0, -1, 0}; 8 const int dy[] = {0, 1, 0, -1}; 9 10 struct Edge { 11 int nex, v, c; 12 }edge[M << 1]; int top = 1; 13 14 struct Eg { 15 int u, v, len; 16 inline bool operator <(const Eg &w) const { 17 return len < w.len; 18 } 19 }eg[M]; 20 21 int e[N], d[N]; 22 std::queue<int> Q; 23 24 inline void add(int x, int y, int z) { 25 top++; 26 edge[top].v = y; 27 edge[top].c = z; 28 edge[top].nex = e[x]; 29 e[x] = top; 30 31 top++; 32 edge[top].v = x; 33 edge[top].c = z; 34 edge[top].nex = e[y]; 35 e[y] = top; 36 return; 37 } 38 39 inline bool BFS(int s, int t) { 40 memset(d, 0, sizeof(d)); 41 d[s] = 1; 42 Q.push(s); 43 while(!Q.empty()) { 44 int x = Q.front(); 45 Q.pop(); 46 for(int i = e[x]; i; i = edge[i].nex) { 47 int y = edge[i].v; 48 if(!edge[i].c || d[y]) { 49 continue; 50 } 51 d[y] = d[x] + 1; 52 Q.push(y); 53 } 54 } 55 return d[t]; 56 } 57 58 int DFS(int x, int t, int maxF) { 59 if(x == t) { 60 return maxF; 61 } 62 int ans = 0; 63 for(int i = e[x]; i; i = edge[i].nex) { 64 int y = edge[i].v; 65 if(!edge[i].c || d[x] + 1 != d[y]) { 66 continue; 67 } 68 int temp = DFS(y, t, std::min(edge[i].c, maxF - ans)); 69 if(!temp) { 70 d[y] = INF; 71 } 72 ans += temp; 73 edge[i].c -= temp; 74 edge[i ^ 1].c += temp; 75 if(ans == maxF) { 76 break; 77 } 78 } 79 return ans; 80 } 81 82 inline int solve(int s, int t) { 83 int ans = 0; 84 while(BFS(s, t)) { 85 ans += DFS(s, t, INF); 86 } 87 return ans; 88 } 89 90 int main() { 91 int n, m, L, s, t; 92 scanf("%d%d", &n, &m); 93 for(int i = 1; i <= m; i++) { 94 scanf("%d%d%d", &eg[i].u, &eg[i].v, &eg[i].len); 95 } 96 scanf("%d%d%d", &s, &t, &L); 97 std::sort(eg + 1, eg + m + 1); 98 int i; 99 for(i = 1; i <= m; i++) { 100 if(eg[i].len == L) { 101 break; 102 } 103 add(eg[i].u, eg[i].v, 1); 104 } 105 int ans = solve(s, t); 106 memset(e, 0, sizeof(e)); 107 top = 1; 108 for(; i <= m; i++) { 109 if(eg[i].len == L) { 110 continue; 111 } 112 add(eg[i].u, eg[i].v, 1); 113 } 114 printf("%d", ans + solve(s, t)); 115 return 0; 116 } AC代碼

一開(kāi)始我想把兩遍最小割合成一遍,后來(lái)發(fā)現(xiàn)不行。

比如這個(gè)樣例:

3 2 1 2 1 2 3 3 1 3 2

最小刪邊是0,但是一次最小割是1。

思考:會(huì)不會(huì)有這種情況:你刪掉一個(gè)比給定邊小的邊,使得最大生成樹(shù)無(wú)法達(dá)成(圖不連通)?

應(yīng)該不會(huì),因?yàn)槟銉纱胃畹幕ゲ挥绊?#xff0c;且都成環(huán)。

轉(zhuǎn)載于:https://www.cnblogs.com/huyufeifei/p/10110881.html

總結(jié)

以上是生活随笔為你收集整理的bzoj2561 最小生成树的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。