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 } 

网络流最小割 将源点与睡觉的相连,不睡觉的与汇点相连。朋友之间相连,跑最小割既是答案。

posted on 2016-03-18 06:01  xiyuedong  阅读(140)  评论(0编辑  收藏  举报