1934: [Shoi2007]vote vote of GoodwillIf everyone is regarded as a node, the test instructions is equivalent to the minimum cost of dividing the set of points into 2 separate parts; we take the point of approval to a margin of 1 on the sink point, and from the origin point to the opposing point is an edge with a flow of 1; each pair of friends has a capacity of 1 edge; Then the minimum cost is the minimum cut from the source to the sink, and the minimum cut = = maximum flow;
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> using namespace std;
const int Mn = + Ten, Me = MN * MN * 2;
int hd[mn],nxt[me],to[me],f[me],cnt;
int STEP[MN],QUE[MN];
int s,t;
int n,m;
inline void Add (int x,int y,int z) {to[cnt] = y;
F[CNT] = Z;
NXT[CNT] = hd[x];
HD[X] = cnt++;
TO[CNT] = x;
F[CNT] = 0;
NXT[CNT] = hd[x];
HD[X] = cnt++;
} inline int zeng (int x,int flow) {if (x = = T) return flow;
int res (0); for (int i = hd[x];~i && res < flow; i = Nxt[i]) if (F[i] && step[to[i]] = = Step[x] + 1) {int dt = Z
Eng (To[i],min (flow-res,f[i));
F[i]-= dt,f[1^i] + = dt,res + = DT;
} if (!res) step[x] =-1;
return res;
} inline bool Check () {memset (step,-1,sizeof step);
int h = 1, t = 2;
QUE[1] = S;
Step[s] = 0;
while (H < t) {int sta = que[h++];
for (int i = hd[sta];~i; i = Nxt[i]) if (F[i] && step[to[i]] = =-1) {Step[to[i]] = Step[sta] + 1;
que[t++] = To[i]; }} RETUrn ~step[t];
} inline int dinic () {int res (0);
while (check ()) Res + = Zeng (S,0X7FFFFFFF);
return res;
} int main () {memset (hd,-1,sizeof HD);
scanf ("%d%d", &n,&m);
S = 0, T = n+1;
for (int i = 1,x; I <= n; i++) {scanf ("%d", &x);
if (x) Add (s,i,1);
else Add (i,t,1);
} for (int i = 1,x,y; I <= m; i++) {scanf ("%d%d", &x,&y);
Add (x,y,1);
Add (y,x,1);
} printf ("%d\n", Dinic ());
return 0; }