【poj3281】【最大流】Dining
2013-03-20 21:59
387 查看
一道最大流的简单题。将食物和饮料分别看成一个点集,食物放在左边(记为f[i]),饮料放在右边(记为d[i])。然后将每头牛拆成两个点k,k'
然后开始建图:
1、对于每头牛喜欢的食物和饮料:添加edge(f[i],k,1),edge(d[i],k',1),edge(k,k',1),这样做的目的是为了限制每头牛只能享用一种食物和饮料。
2、对于每个食物和饮料:添加edge(s,f[i],1),edge(d[i],t,1),这样做的目的是限制一种食物和饮料只能选一次。
这样在原图上做一次最大流即为所求,要注意的是拆点时一定要注意好点的映射关系,不能重复映射。
代码:
然后开始建图:
1、对于每头牛喜欢的食物和饮料:添加edge(f[i],k,1),edge(d[i],k',1),edge(k,k',1),这样做的目的是为了限制每头牛只能享用一种食物和饮料。
2、对于每个食物和饮料:添加edge(s,f[i],1),edge(d[i],t,1),这样做的目的是限制一种食物和饮料只能选一次。
这样在原图上做一次最大流即为所求,要注意的是拆点时一定要注意好点的映射关系,不能重复映射。
代码:
#include<cstdio> #include<cstring> using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 500; const int maxm = 50000; struct Edge { int c,pos; int next; }E[maxm]; int dis[maxn],gap[maxn],pre[maxn],cur[maxn]; int head[maxn]; int NE = 0; int n,f,d,add; int s,t,nodenum; void init() { freopen("poj3281.in","r",stdin); freopen("poj3281.out","w",stdout); } void insert(int u,int v,int c) { E[NE].c = c;E[NE].pos = v; E[NE].next = head[u];head[u] = NE++; E[NE].c = 0;E[NE].pos = u; E[NE].next = head[v];head[v] = NE++; } inline void checkmin(int &a,int b) { if(a == -1 || a > b)a = b; } void readdata() { memset(head,-1,sizeof(head)); scanf("%d%d%d",&n,&f,&d); add = (n << 1); for(int i = 1;i <= n;i++) { int fo,dr; scanf("%d%d",&fo,&dr); for(int j = 1;j <= fo;j++) { int tmp; scanf("%d",&tmp); insert(tmp + add,i,1); } for(int j = 1;j <= dr;j++) { int tmp; scanf("%d",&tmp); insert(i + n,tmp + add + f,1); } insert(i,i + n,1); } } int sap() { memset(dis,0,sizeof(dis)); memset(gap,0,sizeof(gap)); for(int i = s;i <= t;i++)cur[i] = head[i]; int u = pre[s] = s,maxflow = 0,aug = -1; gap[0] = nodenum; while(dis[s] < nodenum) { loop: for(int &i = cur[u];i != -1;i = E[i].next) { int v = E[i].pos; if(E[i].c && dis[u] == dis[v] + 1) { checkmin(aug,E[i].c); pre[v] = u; u = v; if(v == t) { maxflow += aug; for(u = pre[u];v != s;v = u,u = pre[u]) { E[cur[u]].c -= aug; E[cur[u]^1].c += aug; } aug = -1; } goto loop; } } int mind = nodenum; for(int i = head[u];i != -1;i = E[i].next) { int v = E[i].pos; if(E[i].c && (mind > dis[v])) { cur[u] = i; mind = dis[v]; } } if((--gap[dis[u]]) == 0)break; gap[dis[u] = mind + 1]++; u = pre[u]; } return maxflow; } void solve() { s = 0,t = n * 2 + f + d + 1; nodenum = t + 1; for(int i = 1;i <= f;i++)insert(s,i + add,1); for(int i = 1;i <= d;i++)insert(i + add + f,t,1); printf("%d\n",sap()); } int main() { init(); readdata(); solve(); return 0; }
相关文章推荐
- POJ3281_Dining_最大流::分配问题
- POJ3281--Dining(最大流)
- [poj3281]Dining(最大流+拆点)
- poj3281 Dining-网络流最大流-多对一的匹配
- poj3281 Dining(经典最大流+拆点)
- poj3281 dining 经典最大流建模方法
- [POJ3281]Dining 最大流(建图奇葩)
- 【POJ3281 Dining 】最大流
- 【网络流-最大流-Dinic-建模】POJ3281 Dining:Pascal 解法
- POJ3281-Dining(最大流)
- poj3281-Dining ,最大流量,内置图
- poj3281 Dining 最大流
- POJ3281 Dining 最大流
- POJ3281 Dining 求最大流
- poj3281 Dining 最大流
- 【poj3281】Dining 最大流
- POJ3281 Dining (拆点+最大流)
- POJ3281 Dining(拆点构图 + 最大流)
- (拆点+最大流)POJ3281 Dining
- poj3281 Dining(最大流)