1. 程式人生 > >BZOJ-1934: [Shoi2007]Vote 善意的投票 (網絡流最小割)

BZOJ-1934: [Shoi2007]Vote 善意的投票 (網絡流最小割)

最小割 sof clas ear tdi print sizeof c++ max

1934: [Shoi2007]Vote 善意的投票

Time Limit: 1 Sec Memory Limit: 64 MB
Submit: 2353 Solved: 1470
[Submit][Status][Discuss]

Description

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

Input

第一行只有兩個整數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不會重復。

Output

只需要輸出一個整數,即可能的最小沖突數。

Sample Input

3 3
1 0 0
1 2
1 3
3 2

Sample Output

1

HINT

在第一個例子中,所有小朋友都投贊成票就能得到最優解

Source

Day2

設一個s一個t 每一個小盆友i支持午覺的由s向他連一條權值為1的邊,不支持的由i向t連一條邊
小盆友直接互相連一條權值為1的邊,從s到t跑一遍最小割即可 由於要建雙向邊,所以邊的範圍是n*(n-1)!!!!!!!!!!!
 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 typedef long long LL;
 4 const int MAX=305;
 5 const int M=MAX*MAX;
 6 int n,m,s,t;
 7 int tot,head[MAX],adj[M],wei[M],next[M];
 8 int deep[MAX],cur[MAX];
 9 inline int read(){
10     int
an=0,x=1;char c=getchar(); 11 while (c<0 || c>9) {if (c==-) x=-1;c=getchar();} 12 while (c>=0 && c<=9) {an=(an<<3)+(an<<1)+c-0;c=getchar();} 13 return an*x; 14 } 15 void addedge(int u,int v,int w){ 16 tot++;adj[tot]=v,wei[tot]=w,next[tot]=head[u],head[u]=tot; 17 } 18 bool bfs(){ 19 int i,j,u; 20 memset(deep,127,sizeof(deep)); 21 deep[s]=0; 22 queue <int> q;q.push(s); 23 while (!q.empty()){ 24 u=q.front();q.pop(); 25 for (i=head[u];i;i=next[i]){ 26 if (deep[adj[i]]>1e9 && wei[i]>0) 27 deep[adj[i]]=deep[u]+1,q.push(adj[i]); 28 } 29 } 30 return deep[t]<1e9; 31 } 32 int dfs(int x,int flo){ 33 if (x==t || flo==0) return flo; 34 int j; 35 for (int &i=cur[x];i;i=next[i]){ 36 if (deep[adj[i]]==deep[x]+1 && wei[i]>0){ 37 j=dfs(adj[i],min(flo,wei[i])); 38 if (j){ 39 wei[i]-=j,wei[i^1]+=j; 40 return j; 41 } 42 } 43 } 44 return 0; 45 } 46 int main(){ 47 freopen ("vote.in","r",stdin);freopen ("vote.out","w",stdout); 48 int i,j,u,v; 49 n=read(),m=read();tot=1;s=n+1,t=n+2; 50 for (i=1;i<=n;i++){ 51 u=read(); 52 if (u==1) addedge(s,i,1),addedge(i,s,0); 53 else addedge(i 54 ,t,1),addedge(t,i,0); 55 } 56 for (i=1;i<=m;i++){ 57 u=read();v=read(); 58 addedge(u,v,1),addedge(v,u,1); 59 } 60 int flow=0,dd; 61 while (bfs()){ 62 for (i=1;i<=n+2;i++) cur[i]=head[i]; 63 while (dd=dfs(s,1e9)) flow+=dd; 64 } 65 printf("%d",flow); 66 return 0; 67 }

BZOJ-1934: [Shoi2007]Vote 善意的投票 (網絡流最小割)