您的位置:首页 > 其它

POJ3281 Dining 最大流 邻接表[模板]

2011-09-06 22:05 323 查看
不错的构图题。

思路:和一般的最大流图论题一样,难点在构图上。

刚开始有点想用二分,但其实不用什么二分匹配,有二分的思想即可,把cow二分成两批。即一个点拆成相连的两个点。

然后左边是food的点,右边是drink的点。

具体看图一目了然。



#include<iostream>

#include<queue>

#include<algorithm>

using namespace std;

const int N=405;

const int M=100000;

int n,f,d;

int edgehead
;

int k=1;

bool visit
;

int pre
;

int start,final;

struct

{

int v,w,next,re;

}edge[M];

void addedge(int a,int b)

{

edge[k].v=b;

edge[k].w=1;

edge[k].next=edgehead[a];

edge[k].re=k+1;

edgehead[a]=k++;

edge[k].v=a;

edge[k].w=0;

edge[k].next=edgehead[b];

edge[k].re=k-1;

edgehead[b]=k++;

}

bool bfs()

{

memset(visit,0,sizeof(visit));

memset(pre,0,sizeof(pre));

queue<int> que;

que.push(start);

visit[start]=true;

pre[start]=0;

while(!que.empty())

{

int now=que.front();

que.pop();

for(int i=edgehead[now];i!=0;i=edge[i].next)

{

if(!visit[edge[i].v]&&edge[i].w>0)

{

que.push(edge[i].v);

visit[edge[i].v]=true;

pre[edge[i].v]=i;

if(edge[i].v==final)

return true;

}

}

}

return false;

}

void solve()

{

int ans=0;

while(bfs())

{

int now=final;

while(pre[now]!=0)

{

int tmp=pre[now];

edge[tmp].w=0;

edge[edge[tmp].re].w=1;

now=edge[edge[tmp].re].v;

}

ans++;

}

printf("%d\n",ans);

}

int main()

{

scanf("%d%d%d",&n,&f,&d);

int a,b;

start=2*n+f+d+1;

final=2*n+f+d+2;

for(int i=1;i<=f;i++)

{

addedge(start,2*n+i);

}

for(int i=1;i<=d;i++)

{

addedge(2*n+f+i,final);

}

for(int i=1;i<=n;i++)

{

scanf("%d%d",&a,&b);

int to;

//addedge(start,)

for(int j=1;j<=a;j++)

{

scanf("%d",&to);

//addedge(start,n*2+to);

addedge(n*2+to,i);

}

for(int j=1;j<=b;j++)

{

scanf("%d",&to);

addedge(n+i,n*2+f+to);

//addedge(n*2+f+to,final);

}

addedge(i,n+i);

}

solve();

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: