题解:
一道挺水的最小割,然而并不会做。
建立超级源汇点,希望切尔西赢的从S向它连容量为1的边,希望切尔西输的从它向T连容量为1的边。在朋友之间连一条双向边,答案就是最小割。
如果存在一条从S到T的路径,相当于产生了冲突。必须说谎(割掉到S或T的边)或者与朋友意见不统一(割掉和朋友的边)
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<time.h>
#include<vector>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int N=1e5+10;
const int mod=1e9+7;
const double eps=1e-8;
const int inf=0x3f3f3f3f;
int n,m,E,S,T,a[N];
int fir[N],nex[N<<1],arr[N<<1],cap[N<<1],len[N<<1],cur[N<<1],dis[N];
queue<int> q;
namespace FastIO {
template<typename tp> inline void read(tp &x) {
x=0; register char c=getchar(); register bool f=0;
for(;c<'0'||c>'9';f|=(c=='-'),c = getchar());
for(;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0',c = getchar());
if(f) x=-x;
}
template<typename tp> inline void write(tp x) {
if (x==0) return (void) (putchar('0'));
if (x<0) putchar('-'),x=-x;
int pr[20]; register int cnt=0;
for (;x;x/=10) pr[++cnt]=x%10;
while (cnt) putchar(pr[cnt--]+'0');
}
template<typename tp> inline void writeln(tp x) {
write(x);
putchar('\n');
}
}
using namespace FastIO;
void Add_Edge(int x,int y,int c) {
nex[++E]=fir[x];
cap[E]=c;
fir[x]=E; arr[E]=y;
nex[++E]=fir[y];
cap[E]=0;
fir[y]=E; arr[E]=x;
}
void Init() {
read(n); read(m); E=1;
S=0,T=n+1;
for (int i=1;i<=n;i++) read(a[i]);
for (int i=1;i<=n;i++) {
if (a[i]) Add_Edge(S,i,1);
else Add_Edge(i,T,1);
}
for (int i=1;i<=m;i++) {
int x,y; read(x); read(y);
Add_Edge(x,y,1);
Add_Edge(y,x,1);
}
}
int bfs() {
memset(dis,0x3f,sizeof(dis));
dis[S]=0; q.push(S);
while (!q.empty()) {
int u=q.front(); q.pop();
for (int i=fir[u];i;i=nex[i]) {
int v=arr[i];
if (dis[v]<inf||!cap[i]) continue;
dis[v]=dis[u]+1;
q.push(v);
}
}
return dis[T]<inf;
}
int dfs(int x,int maxflow) {
if (x==T||!maxflow) return maxflow;
int ans=0;
for (int i=cur[x];i;cur[x]=i=nex[i]) {
int v=arr[i];
if (dis[v]==dis[x]+1&&cap[i]) {
int del=dfs(v,min(maxflow,cap[i]));
ans+=del; maxflow-=del;
cap[i]-=del; cap[i^1]+=del;
}
}
return ans;
}
int main() {
Init();
int flow=0;
while (bfs()) {
for (register int i=0;i<=n+1;i++) cur[i]=fir[i];
flow+=dfs(S,inf);
}
printf("%d",flow);
return 0;
}