【bzoj2521】[Shoi2010]最小生成树 网络流最小割
生活随笔
收集整理的這篇文章主要介紹了
【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]最小生成树 网络流最小割的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 通过webview调起支
- 下一篇: LightOJ 1026 桥 1063