洛谷 P2057 善意的投票(網路流最小割)

2022-03-04 22:00:03 字數 1711 閱讀 1020

幼兒園裡有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 21 3

3 2

輸出樣例#1:

1

2≤n≤300,1≤m≤n(n-1)/2。

solution:

題意大致就是有n個人有兩種不同的意見並且有許多朋友,需要讓朋友間盡可能的統一意見(少發生衝突),如果乙個人違反自己的本意也算衝突,求最少的衝突。。。明眼人直接發現是最小割,兩種意見可以看作源點s和t,我們需要做的是割最少的邊使得s和t成為兩個不同的集合,解釋:割掉的邊相當於1次衝突(因為若某邊被割走,則顯然這條邊相連的兩個點分別通向了s和t,所以算是一次衝突),當s和t還連通時則必然存在一條路徑,這樣肯定會有衝突,所以需要使得s和t孤立。

實現時這樣建圖:直接將s連向同意的人,t連向不同意的人,若兩人是朋友,則在他們之間連一條雙向邊(這裡有些人不理解,若兩個人有衝突,則只需要其中任意乙個人改變意見就行了,簡單說可能是a同意b的意見或者b同意a的意見,只需割掉一條邊,但是有兩種情況,所以建雙向邊)。

最後就是求最小割了,直接套上最大流的模板就ok了。

1

//luogu-judger-enable-o2

2 #include3

#define il inline

4using

namespace

std;

5const

int n=100005,inf=23333333;6

int n,m,s,t=520,h[n],cnt=1

,dis[n],ans;

7struct

edgee[n*4

];10 il void add(int u,int v,int

w)11

15 queueq;

16 il bool

bfs()

1726

return dis[t]!=-1;27

}28 il int dfs(int u,int

op)2943}

44if(!flow)dis[u]=-1;45

return

flow;46}

47int

main()

4856

for(int i=1;i<=m;i++)

60while(bfs())ans+=dfs(s,inf);

61 cout<62return0;

63 }

洛谷P2057 SHOI2007 善意的投票

題目鏈結 這道題是最小割的乙個經典應用 劃分集合。題目的意思就是就是將所有的小朋友分為兩個集合 同意睡覺和不同意睡覺的。不同的集合之間的邊都要斷開。我們設 s 為投票結果為不想睡覺的小朋友 顏色為0 的集合 t 為投票結果為想睡覺的小朋友 顏色為1 的集合。然後對於乙個小朋友 i 設他的 顏色 為x...

P2057 SHOI2007 善意的投票

題目描述 幼兒園裡有n個小朋友打算通過投票來決定睡不睡午覺。對他們來說,這個問題並不是很重要,於是他們決定發揚謙讓精神。雖然每個人都有自己的主見,但是為了照顧一下自己朋友的想法,他們也可以投和自己本來意願相反的票。我們定義一次投票的衝突數為好朋友之間發生衝突的總數加上和所有和自己本來意願發生衝突的人...

題解 P2057 SHOI2007 善意的投票

傳送們 幼兒園裡有n個小朋友打算通過投票來決定睡不睡午覺。對他們來說,這個問題並不是很重要,於是他們決定發揚謙讓精神。雖然每個人都有自己的主見,但是為了照顧一下自己朋友的想法,他們也可以投和自己本來意願相反的票。我們定義一次投票的衝突數為好朋友之間發生衝突的總數加上和所有和自己本來意願發生衝突的人數...