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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【bzoj2521】[Shoi2010]最小生成树 网络流最小割

發布時間:2023/12/18 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【bzoj2521】[Shoi2010]最小生成树 网络流最小割 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目描述

Secsa最近對最小生成樹問題特別感興趣。他已經知道如果要去求出一個n個點、m條邊的無向圖的最小生成樹有一個Krustal算法和另一個Prim的算法。另外,他還知道,某一個圖可能有多種不同的最小生成樹。例如,下面圖?3中所示的都是圖?2中的無向圖的最小生成樹:

?

當然啦,這些都不是今天需要你解決的問題。Secsa想知道對于某一條無向圖中的邊AB,至少需要多少代價可以保證AB邊在這個無向圖的最小生成樹中。為了使得AB邊一定在最小生成樹中,你可以對這個無向圖進行操作,一次單獨的操作是指:先選擇一條圖中的邊?P1P2,再把圖中除了這條邊以外的邊,每一條的權值都減少1。如圖?4所示就是一次這樣的操作:

輸入

輸入文件的第一行有3個正整數n、m、Lab分別表示無向圖中的點數、邊數、必須要在最小生成樹中出現的AB邊的標號。 接下來m行依次描述標號為1,2,3…m的無向邊,每行描述一條邊。每個描述包含3個整數x、y、d,表示這條邊連接著標號為x、y的點,且這條邊的權值為d。 輸入文件保證1<=x,y<=N,x不等于y,且輸入數據保證這個無向圖一定是一個連通圖。

輸出

輸出文件只有一行,這行只有一個整數,即,使得標號為Lab邊一定出現最小生成樹中的最少操作次數。

樣例輸入

4 6 1
1 2 2
1 3 2
1 4 3
2 3 2
2 4 4
3 4 5

樣例輸出

1


題解

網絡流最小割

除了這條邊以外其它邊都-1,相當于其它邊不變,這條邊+1。

然后考慮Kruscal求最小生成樹的方法,一條邊一定出現在最小生成樹上,等價于所有邊權小于等于它的邊不能使得這兩個端點連通。

于是轉化為最小割問題。

對于每條長度小于等于給定的邊,連容量為 給定長度-當前長度+1 的邊,然后跑最小割即可。

#include <queue> #include <cstdio> #include <cstring> #define N 510 #define K 810 #define M 100010 using namespace std; queue<int> q; int x[K] , y[K] , z[K] , head[N] , to[M] , val[M] , next[M] , cnt = 1 , s , t , dis[N]; void add(int x , int y , int z) {to[++cnt] = y , val[cnt] = z , next[cnt] = head[x] , head[x] = cnt;to[++cnt] = x , val[cnt] = z , next[cnt] = head[y] , head[y] = cnt; } bool bfs() {int x , i;memset(dis , 0 , sizeof(dis));while(!q.empty()) q.pop();dis[s] = 1 , q.push(s);while(!q.empty()){x = q.front() , q.pop();for(i = head[x] ; i ; i = next[i]){if(val[i] && !dis[to[i]]){dis[to[i]] = dis[x] + 1;if(to[i] == t) return 1;q.push(to[i]);}}}return 0; } int dinic(int x , int low) {if(x == t) return low;int temp = low , i , k;for(i = head[x] ; i ; i = next[i]){if(val[i] && dis[to[i]] == dis[x] + 1){k = dinic(to[i] , min(temp , val[i]));if(!k) dis[to[i]] = 0;val[i] -= k , val[i ^ 1] += k;if(!(temp -= k)) break;}}return low - temp; } int main() {int n , m , p , i , ans = 0;scanf("%d%d%d" , &n , &m , &p);for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%d" , &x[i] , &y[i] , &z[i]);s = x[p] , t = y[p];for(i = 1 ; i <= m ; i ++ )if(i != p && z[i] <= z[p])add(x[i] , y[i] , z[p] - z[i] + 1);while(bfs()) ans += dinic(s , 1 << 30);printf("%d\n" , ans);return 0; }

?

?

轉載于:https://www.cnblogs.com/GXZlegend/p/7355935.html

總結

以上是生活随笔為你收集整理的【bzoj2521】[Shoi2010]最小生成树 网络流最小割的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。