P2057 [SHOI2007] 善意的投票 / [JLOI2010] 冠军调查

P2057 [SHOI2007] 善意的投票 / [JLOI2010] 冠军调查

看到数据范围一眼网络流:

对于每个人,将其拆成两个点x,x,对应两种选择。
我们对x,x 连一条流量为 inf 的边,表示这个点不能被割。然后分别连边S>x x>T 流量根据点的初始选择而定,但是注意,流量应该分别设置为1和2,而非0和1,不然就不能选择性的割了

然后对于他的朋友,直接交叉连边 x>yy>x 边权都是1。

然后最后把答案减掉 n 就好了(抵消初始流量设置)

Code:

#include<bits/stdc++.h>
const int N=605;
const int inf=1e9;
using namespace std;
int n,m,e_cnt=1,S,T,ans;
struct Edge{
int to,nxt,flow;
}e[N*N*2];
int head[N];
void add(int x,int y,int fl)
{
e[++e_cnt]=Edge{y,head[x],fl};
head[x]=e_cnt;
e[++e_cnt]=Edge{x,head[y],0};
head[y]=e_cnt;
}
queue<int> Q;
int dl[N],dis[N],flow[N],pre[N];
void init()
{
for(int i=S;i<=T;i++)dis[i]=inf,flow[i]=0;
}
bool spfa(int s,int t)
{
init();
Q.push(s);
dis[s]=0;flow[s]=inf;
while(!Q.empty())
{
int u=Q.front();Q.pop();
dl[u]=0;
//cout<<u<<":\n";
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to,fl=e[i].flow;
//cout<<v<<" "<<"="<<dis[v]<<" "<<dis[u]+1<<" "<<fl<<"\n";
if(dis[v]>dis[u]+1&&fl)
{
flow[v]=min(fl,flow[u]);
dis[v]=dis[u]+1;
pre[v]=i;
if(!dl[v])
{
Q.push(v);
dl[v]=1;
}
}
}
//cout<<"\n";
}
//cout<<flow[t]<<"\n";
return flow[t];
}
void dinic()
{
while(spfa(S,T))
{
int now=T;
ans+=flow[T];
while(now)
{
//cout<<"now:"<<now<<"\n";
int i=pre[now];
e[i].flow-=flow[T];e[i^1].flow+=flow[T];
now=e[i^1].to;
}
}
}
void work()
{
cin>>n>>m;
S=0,T=n+n+1;
for(int i=1,opt;i<=n;i++)
{
scanf("%d",&opt);
if(opt==0)
{
add(S,i,2); add(i+n,T,1);
}
else
{
add(S,i,1); add(i+n,T,2);
}
add(i,i+n,inf);
}
for(int i=1,x,y;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x,y+n,1);
add(y,x+n,1);
}
dinic();
printf("%d",ans-n);
}
int main()
{
//freopen("vote.in","r",stdin);
//freopen("vote.out","w",stdout);
work();
return 0;
}
posted @   liuboom  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示