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;
}
思路:和一般的最大流图论题一样,难点在构图上。
刚开始有点想用二分,但其实不用什么二分匹配,有二分的思想即可,把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;
}
相关文章推荐
- POJ3281_Dining_最大流::分配问题
- poj3281最大流(模板)
- hdu1569 方格取数(2) (最大流 E_K)模板 邻接表
- poj3281-Dining ,最大流,建图
- POJ3281 Dining(最大流+拆点)
- EK(BFS)求最大流的算法模板(邻接表)
- POJ 1469 COURSES(二分图最大匹配) (矩阵和邻接表的模板题)
- POJ3281 Dining,最大流EK算法
- 【poj3281】【最大流】Dining
- POJ3281 Dining 最大流
- poj3281-Dining ,最大流量,内置图
- POJ3281-Dining(最大流)
- POJ3281 Dining 求最大流
- [poj3281]Dining(最大流+拆点)
- poj3281 dining 经典最大流建模方法
- POJ3281 Dining 最大流
- POJ_3281_Dining(最大流dinic模板)
- POJ3281--Dining(最大流)
- poj3281 Dining(最大流)
- 【POJ3281】Dining【最大流】