【BZOJ】【1934】【SHOI 2007】Vote 善意的投票
网络流/最小割
简单题= =直接利用最小割的性质:
割掉这些边后,将所有点分成了两部分(两个连通块),我们可以假定与S相连的是投赞成票,与T相连的是投反对票。
那么如果一个小朋友原本意愿是睡觉,那么连边 S->i ,边权为1,表示如果割掉这条边(即让他投违反意愿的票)则冲突数+1。原本意愿是不睡觉的连 i->T,边权为1,意义同理。
然后处理“好朋友”的情况,对每对好朋友,连边 i->j 和 j->i,边权均为1,表示如果割掉这条边(则两个点所属不同块)则冲突数+1。
要求总冲突数(割掉的边数)最小,所以最小割即为答案。
(如果存在一条S->T的路径,那这个路径上的小朋友是投赞成呢还是反对呢?一定要表态的啊……所以必须割掉啊……)
1 /************************************************************** 2 Problem: 1934 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:16 ms 7 Memory:4408 kb 8 ****************************************************************/ 9 10 //BZOJ 1934 11 #include<vector> 12 #include<cstdio> 13 #include<cstring> 14 #include<cstdlib> 15 #include<iostream> 16 #include<algorithm> 17 #define rep(i,n) for(int i=0;i<n;++i) 18 #define F(i,j,n) for(int i=j;i<=n;++i) 19 #define D(i,j,n) for(int i=j;i>=n;--i) 20 #define pb push_back 21 using namespace std; 22 inline int getint(){ 23 int v=0,sign=1; char ch=getchar(); 24 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} 25 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} 26 return v*sign; 27 } 28 const int N=320,M=200000,INF=~0u>>2; 29 typedef long long LL; 30 /******************tamplate*********************/ 31 int n,m; 32 struct edge{ 33 int from,to,v; 34 }; 35 inline int pack(int i,int j){return (i-1)*m+j;} 36 struct Net{ 37 edge E[M]; 38 int head[N],next[M],cnt; 39 void add(int x,int y,int v){ 40 E[++cnt]=(edge){x,y,v}; 41 next[cnt]=head[x]; head[x]=cnt; 42 E[++cnt]=(edge){y,x,0}; 43 next[cnt]=head[y]; head[y]=cnt; 44 } 45 int s,t,cur[N],d[N],Q[N]; 46 void init(){ 47 n=getint();m=getint(); 48 cnt=1; 49 s=0; t=n+1; 50 F(i,1,n) 51 if (getint()) add(s,i,1); 52 else add(i,t,1); 53 int x,y; 54 F(i,1,m){ 55 x=getint(); y=getint(); 56 add(x,y,1); 57 add(y,x,1); 58 } 59 } 60 bool mklevel(){ 61 memset(d,-1,sizeof d); 62 d[s]=0; 63 int l=0,r=-1; 64 Q[++r]=s; 65 while(l<=r){ 66 int x=Q[l++]; 67 for(int i=head[x];i;i=next[i]) 68 if (d[E[i].to]==-1 && E[i].v){ 69 d[E[i].to]=d[x]+1; 70 Q[++r]=E[i].to; 71 } 72 } 73 return d[t]!=-1; 74 } 75 int dfs(int x,int a){ 76 if (x==t||a==0) return a; 77 int flow=0; 78 for(int &i=cur[x];i && flow<a;i=next[i]) 79 if (d[E[i].to]==d[x]+1 && E[i].v){ 80 int f=dfs(E[i].to,min(a-flow,E[i].v)); 81 E[i].v-=f; 82 E[i^1].v+=f; 83 flow+=f; 84 } 85 if (!flow) d[x]=-1; 86 return flow; 87 } 88 int Dinic(){ 89 int flow=0; 90 while(mklevel()){ 91 F(i,s,t) cur[i]=head[i]; 92 flow+=dfs(s,INF); 93 } 94 return flow; 95 } 96 }G1; 97 int main(){ 98 #ifndef ONLINE_JUDGE 99 freopen("1934.in","r",stdin); 100 freopen("1934.out","w",stdout); 101 #endif 102 G1.init(); 103 printf("%d\n",G1.Dinic()); 104 return 0; 105 }