1 #include<cstdio> 2 #include<iostream> 3 #define M 100000 4 #include<cstring> 5 using namespace std; 6 int cnt=1,head[M],next[10*M],u[10*M],v[10*M],n,m,d[M],q[M],ans; 7 void jia(int a1,int a2,int a3) 8 { 9 cnt++; 10 u[cnt]=a2; 11 v[cnt]=a3; 12 next[cnt]=head[a1]; 13 head[a1]=cnt; 14 return; 15 } 16 bool bfs() 17 { 18 memset(d,0,sizeof(int)*(n+1)); 19 int h=0,t=1; 20 q[1]=0; 21 d[0]=1; 22 for(;h<t;) 23 { 24 h++; 25 int p=q[h]; 26 for(int i=head[p];i;i=next[i]) 27 if(!d[u[i]]&&v[i]) 28 { 29 d[u[i]]=d[p]+1; 30 if(d[n]) 31 return 1; 32 t++; 33 q[t]=u[i]; 34 } 35 } 36 return 0; 37 } 38 int dinic(int s,int f) 39 { 40 if(s==n) 41 return f; 42 int rest=f; 43 for(int i=head[s];i&&rest;i=next[i]) 44 if(v[i]&&d[u[i]]==d[s]+1) 45 { 46 int now=dinic(u[i],min(rest,v[i])); 47 if(!now) 48 d[u[i]]=0; 49 v[i]-=now; 50 v[i^1]+=now; 51 rest-=now; 52 } 53 return f-rest; 54 } 55 int main() 56 { 57 scanf("%d%d",&n,&m); 58 for(int i=1;i<=n;i++) 59 { 60 int a1; 61 scanf("%d",&a1); 62 if(a1) 63 { 64 jia(0,i,1); 65 jia(i,0,0); 66 } 67 else 68 { 69 jia(i,n+1,1); 70 jia(n+1,i,0); 71 } 72 } 73 for(int i=1;i<=m;i++) 74 { 75 int a1,a2; 76 scanf("%d%d",&a1,&a2); 77 jia(a1,a2,1); 78 jia(a2,a1,0); 79 jia(a2,a1,1); 80 jia(a1,a2,0); 81 } 82 n++; 83 for(;bfs();) 84 ans+=dinic(0,0x7fffffff); 85 printf("%d\n",ans); 86 return 0; 87 }
网络流最小割 将源点与睡觉的相连,不睡觉的与汇点相连。朋友之间相连,跑最小割既是答案。