bzoj2768(最小割,二者取其一式问题)

来源:互联网 发布:hbuilder下载 mac 编辑:程序博客网 时间:2024/04/30 15:45

一年一度的欧洲足球冠军联赛已经进入了淘汰赛阶段。随着卫冕冠军巴萨罗那的淘汰,英超劲旅切尔西成为了头号热门。新浪体育最近在吉林教育学院进行了一次大规模的调查,调查的内容就是关于切尔西能否在今年问鼎欧洲冠军。新浪体育的记者从各个院系中一共抽取了n位同学作为参与者,大家齐聚一堂,各抒己见。每一位参与者都将发言,阐述自己的看法。参与者的心里都有一个看法,比如FireDancer认为切尔西不可能夺冠,而WaterDancer认为切尔西一定问鼎。但是因为WaterDancer是FireDancer的好朋友,所以可能FireDancer为了迁就自己的好朋友,会在发言中支持切尔西。也就是说每个参与者发言时阐述的看法不一定就是心里所想的。现在告诉你大家心里的想法和参与者的朋友网,希望你能安排每个人的发言内容,使得违心说话的人的总数与发言时立场不同的朋友(对)的总数的和最小。


首先注意朋友之间连边是双向的!!!!以前搞错过

为什么又把数组开小了。。。

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<queue>using namespace std;const int N=5000;const int inf=0x3f3f3f3f;int s,t,n,m;int head[N],cur[N],tot,lev[N];struct aa{int pre,to,flow,cap;}edge[300500];void addedge(int x,int y,int z){edge[++tot].to=y;edge[tot].cap=z;edge[tot].pre=head[x];head[x]=tot;edge[++tot].to=x;edge[tot].cap=0;edge[tot].pre=head[y];head[y]=tot;}bool bfs(){memset(lev,0,sizeof(lev));lev[s]=1;queue<int> q;q.push(s);while (!q.empty()){int u=q.front();q.pop();for (int i=head[u];i;i=edge[i].pre)if (edge[i].cap>edge[i].flow&&!lev[edge[i].to]){lev[edge[i].to]=lev[u]+1;if (edge[i].to==t) return true;q.push(edge[i].to);}}return false;}int dfs(int u,int maxflow){if (u==t||maxflow==0) return maxflow;int ans=0;for (int &i=cur[u];i;i=edge[i].pre)if (lev[edge[i].to]==lev[u]+1){int flow=dfs(edge[i].to,min(maxflow,edge[i].cap-edge[i].flow));ans+=flow;maxflow-=flow;edge[i].flow+=flow;edge[((i-1)^1)+1].flow-=flow;if (maxflow==0) return ans;}return ans;}int work(){int ans=0;while (bfs()){for (int i=s;i<=t;i++) cur[i]=head[i];ans+=dfs(s,inf);}return ans;}int main(){scanf("%d%d",&n,&m);s=0,t=n+1;int x,y;for (int i=1;i<=n;i++) {scanf("%d",&x);if (x) addedge(s,i,1);else addedge(i,t,1);}for (int i=1;i<=m;i++){scanf("%d%d",&x,&y);addedge(x,y,1);addedge(y,x,1);} printf("%d",work());return 0;}

总结

1:二者选其一式问题,对于每一个点,左连S入点,右连T点,不割哪一条边代表选择哪一个决策。点对之间连边,处理不同点对之间决策的处理方式,流量就表示的不选这种决策损失的值,一般问最少会有多少不高兴值之类的,就是这里的最小割

0 0
原创粉丝点击