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

不错的构图题。

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

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

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

具体看图一目了然。

poj <wbr>3281 <wbr>:Dining <wbr>(网络流)

#include<iostream>

#include<queue>
#include<algorithm>
using namespace std;
const int N=405;
const int M=100000;
int n,f,d;
int edgehead[N];
int k=1;
bool visit[N];
int pre[N];
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;
}
posted on 2011-09-06 22:05  不是我干的  阅读(136)  评论(0)    收藏  举报