标签:shoi2007 content online stat href == submit i++ status
在第一个例子中,所有小朋友都投赞成票就能得到最优解
最小割模型。
S向1的人建容量1的边,0的人向T建容量1的边。认识的人互相建容量1的边。
这样求出最小割后,与S相连的点集表示最终选1的人,与T相连表示选0,每条割边表示一个冲突。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define ll long long
#define N 305
using namespace std;
int n,m,S,T,tot,hd[N],d[N],vis[N],cur[N];
struct edge{int v,next,cap,flow;}e[N*N*4];
void adde(int u,int v,int c){
e[tot].v=v;
e[tot].next=hd[u];
e[tot].cap=c;
e[tot].flow=0;
hd[u]=tot++;
}
bool bfs(){
queue<int>q;
memset(vis,0,sizeof(vis));
q.push(S);d[S]=0;
while(!q.empty()){
int u=q.front();q.pop();vis[u]=1;
for(int i=hd[u];~i;i=e[i].next){
int v=e[i].v;
if(e[i].cap<=e[i].flow||vis[v])continue;
d[v]=d[u]+1;q.push(v);
}
}
return vis[T];
}
int dfs(int u,int a){
if(u==T||!a)return a;
int fl=0,f;
for(int i=hd[u];~i;i=e[i].next){
int v=e[i].v;
if(d[v]==d[u]+1&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){
fl+=f;a-=f;
e[i].flow+=f;
e[i^1].flow-=f;
if(a<=0)break;
}
}
return fl;
}
int main(){
scanf("%d%d",&n,&m);
memset(hd,-1,sizeof(hd));
S=0;T=n+1;
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
if(x)adde(S,i,1),adde(i,S,0);
else adde(i,T,1),adde(T,i,0);
}
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
adde(a,b,1);adde(b,a,1);
}
int flow=0;
while(bfs()){
for(int i=S;i<=T;i++)cur[i]=hd[i];
flow+=dfs(S,0x3f3f3f3f);
}
printf("%d",flow);
return 0;
}
标签:shoi2007 content online stat href == submit i++ status
原文地址:http://www.cnblogs.com/wsy01/p/7932137.html