標籤:網路流 最小割
原題 洛谷p2057 善意的投票
題目描述
幼兒園裡有n個小朋友打算通過投票來決定睡不睡午覺。對他們來說,這個問題並不是很重要,於是他們決定發揚謙讓精神。雖然每個人都有自己的主見,但是為了照顧一下自己朋友的想法,他們也可以投和自己本來意願相反的票。我們定義一次投票的衝突數為好朋友之間發生衝突的總數加上和所有和自己本來意願發生衝突的人數。
我們的問題就是,每位小朋友應該怎樣投票,才能使衝突數最小?
輸入輸出格式
輸入格式:
檔案的第一行只有兩個整數n,m,保證有2≤n≤300,1≤m≤n(n-1)/2。其中n代表總人數,m代表好朋友的對數。檔案第二行有n個整數,第i個整數代表第i個小朋友的意願,當它為1時表示同意睡覺,當它為0時表示反對睡覺。接下來檔案還有m行,每行有兩個整數i,j。表示i,j是一對好朋友,我們保證任何兩對i,j不會重複。
輸出格式:
只需要輸出乙個整數,即可能的最小衝突數。
輸入輸出樣例
輸入樣例#1:
3 3
1 0 0
1 2
1 3
3 2
輸出樣例#1:
1 說明
2≤n≤300,1≤m≤n(n-1)/2。
要麼投睡覺要麼不睡,所以應分成兩個集合,因為可以跟著好朋友改意見,所以可以連著邊的人都可以投同乙個票。每個人只有兩種選擇,所以肯定和s點或t點連著,所以如果割變是與源匯點連著,則算是與自己的意願衝突,如果割在朋友間則是與朋友的衝突。每割斷一對好友或自身意願。衝突數加一,所以就是求最小割。最小割等於最大流,用dinic即可。(dinic請看模板dinic模板)
注意的是一對好友之間可以互相改意見,所以直接建雙向邊(注意是雙向邊,和原來演算法的反向邊區分好,這是本題需要,反向邊是為了保證演算法正確,都要建,剛開始我就被坑了)。自己再建乙個s點表示一種最初觀點相同的人,建乙個t點表示另一種。我是投1的連s,投0的人連t。
**在此
#include
#include
#include
#include
#define n 310
#define m 100000
using
namespace
std;
int m,n,ans;
queue
team;
struct ea[m*2];int last[n],dis[n],cnt;
void build(int u,int v,int c)
bool bfs()}}
return dis[306]>-1;
}int dfs(int x,int f)
if(!now)dis[x]=-1;
return now;
}int main()
for(int i=1;i<=m;++i)
while(bfs())
ans+=dfs(305,0x7fffffff);
printf("%d\n",ans);
return
0;}
網路流 最小割
割是一種對網路流點的劃分方式 對於乙個網路流圖g v,e 劃分為s和t兩部分,其中t v s,源點s s,匯點t t 淨流f s,t 表示穿過割 s,t 的流量之和 f s,t f u,v u s,v t 割的容量c s,t 為所有從s到t的邊容量之和 c s,t c u,v u s,v t f s...
網路流之最小割
最小割的相關知識請參見 網路流問題 i.hdu4289 control 題意 給出乙個由n個點,m條邊組成的無向圖。給出兩個點s,t。對於圖中的每個點,去掉這個點都需要一定的花費。求至少多少花費才能使得s和t之間不連通。分析 題意即求最小割,將每個點拆點,點與對應點的邊權為去掉該點的花費,原圖中所有...
網路流最小割 王者之劍
傳送門 不用考慮走的方法,因為一旦合法,即不同時取相鄰的兩個,一定能達到。所以只用考慮怎麼取就行了。把棋盤黑白染色,s到黑點建權值為val的邊,白點到t建權值為val的邊,然後把相鄰的黑白點建一條為inf的邊。求最小割。不得不提一句 邊從零開始建和從一開始建乙個wa乙個a。時相應的正邊和反邊必須對應...