网络流( ISAP + 拆点 )——Dining ( POJ 3281 )
来源:互联网 发布:linux dhcp option 66 编辑:程序博客网 时间:2024/06/15 10:01
题目链接:
http://poj.org/problem?id=3281分析:
一头牛只吃指定的几种食物或饮料,但是每一种食物和饮料都只有一个,给出N头牛及其要求,F种食物和D种饮料,问最多可以满足多少头牛的需要(饮料和食物都满足需求)。题解:
1.建图:需要将每头牛拆成牛1和牛2,然后建立一个源点S,从S出发作边连接每一个食物,容量为1。然后从食物出发向和其对应的牛做边,容量为1。再连接牛1和牛2,容量为1。从牛2出发向与其对应的饮料作边,容量为1。再连接饮料与汇点,容量为1。
//邻接链表存储边int head[Maxn];struct node{ int v, cap; //v为该点连的当前边另一端的点,cap为当前边边的容量 int next;//该点连接的下一条边}edge[80000];void add(int u, int v, int cap)//添加边{ edge[cont].v = v; edge[cont].cap = cap; edge[cont].next = head[u]; head[u] = cont++; edge[cont].v=u; //反向建边,容量为0 edge[cont].cap=0; edge[cont].next=head[v]; head[v] = cont++;}
2.BFS:
int dis[Maxn];int num[Maxn];void BFS(int source,int sink){ queue<int>q; while(!q.empty()) q.pop(); memset(num,0,sizeof(num)); memset(dis,-1,sizeof(dis)); q.push(sink); dis[sink]=0; num[0]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i = head[u]; i! = -1; i = edge[i].next) { int v = edge[i].v; if(dis[v] == -1) { dis[v] = dis[u] + 1; num[dis[v]]++; q.push(v); } } }}
3.ISAP:
int cur[Maxn];int pre[Maxn];int ISAP(int source,int sink,int n){ memcpy(cur,head,sizeof(cur)); int flow=0, u = pre[source] = source; BFS(source, sink); while( dis[source] < n ) { if(u == sink) { int df = INF, pos; for(int i =source;i != sink;i = edge[cur[i]].v) { if(df > edge[cur[i]].cap) { df = edge[cur[i]].cap; pos = i; } } for(int i = source;i != sink;i = edge[cur[i]].v) { edge[cur[i]].cap -= df; edge[cur[i]^1].cap += df; } flow += df; u = pos; } int st; for(st = cur[u];st != -1;st = edge[st].next) { if(dis[edge[st].v] + 1 == dis[u] && edge[st].cap) { break; } } if(st != -1) { cur[u] = st; pre[edge[st].v] = u; u = edge[st].v; } else { if( (--num[dis[u]])==0 ) break; int mind = n; for(int id = head[u];id != -1;id = edge[id].next) { if(mind > dis[edge[id].v] && edge[id].cap != 0) { cur[u] = id; mind = dis[edge[id].v]; } } dis[u] = mind+1; num[dis[u]]++; if(u!=source) u = pre[u]; } } return flow;}
- AC代码:
#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;#define Maxn 2000#define INF 99999999struct node{ int v, cap; int next;}edge[80000];int N,F,D;int cont;int head[Maxn];int dis[Maxn];int num[Maxn];int cur[Maxn];int pre[Maxn];void add(int u, int v, int cap){ edge[cont].v = v; edge[cont].cap = cap; edge[cont].next = head[u]; head[u] = cont++; edge[cont].v=u; edge[cont].cap=0; edge[cont].next=head[v]; head[v] = cont++;}void BFS(int source,int sink){ queue<int>q; while(q.empty()==false) q.pop(); memset(num,0,sizeof(num)); memset(dis,-1,sizeof(dis)); q.push(sink); dis[sink]=0; num[0]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=edge[i].next) { int v = edge[i].v; if(dis[v] == -1) { dis[v] = dis[u] + 1; num[dis[v]]++; q.push(v); } } }}int ISAP(int source,int sink,int n){ memcpy(cur,head,sizeof(cur)); int flow=0, u = pre[source] = source; BFS( source,sink); while( dis[source] < n ) { if(u == sink) { int df = INF, pos; for(int i =source;i != sink;i = edge[cur[i]].v) { if(df > edge[cur[i]].cap) { df = edge[cur[i]].cap; pos = i; } } for(int i = source;i != sink;i = edge[cur[i]].v) { edge[cur[i]].cap -= df; edge[cur[i]^1].cap += df; } flow += df; u = pos; } int st; for(st = cur[u];st != -1;st = edge[st].next) { if(dis[edge[st].v] + 1 == dis[u] && edge[st].cap) { break; } } if(st != -1) { cur[u] = st; pre[edge[st].v] = u; u = edge[st].v; } else { if( (--num[dis[u]])==0 ) break; int mind = n; for(int id = head[u];id != -1;id = edge[id].next) { if(mind > dis[edge[id].v] && edge[id].cap != 0) { cur[u] = id; mind = dis[edge[id].v]; } } dis[u] = mind+1; num[dis[u]]++; if(u!=source) u = pre[u]; } } return flow;}void init(){ memset(head,-1,sizeof(head)); cont=0;}int main(){ int a,b,c; while(~scanf("%d%d%d", &N, &F, &D)) { init(); int S = 0; int T = 2*N+F+D+1; for(int i = 1; i<=F; i++) //建立源点到所有食物 { add(S, i, 1); } for(int i = 1; i<=N; i++) { scanf("%d%d",&a,&b); for(int j = 1;j<=a;j++) { scanf("%d",&c); add(c,F+i,1);//食物到牛 } for(int j = 1;j<=b;j++) { scanf("%d",&c); add(F+i+N,2*N+F+c,1);//牛' 到饮料 } add(F+i,F+i+N,1);//牛 到 牛’ } for(int i = 1;i<=D;i++) { add(2*N+F+i, T,1);//食物 到汇点 } int ans = ISAP(S, T, T+1 ); printf("%d\n",ans); } return 0;}
0 0
- 网络流( ISAP + 拆点 )——Dining ( POJ 3281 )
- poj 3281 Dining isap + 拆点
- POJ 3281 Dining(最大流建图 && ISAP && 拆点)
- Poj 3281 Dining (拆点网络流)
- POJ 3281 Dining 拆点网络流
- POJ 3281 Dining (拆点+ 网络流)
- POJ 3281 Dining( 网络流, Dinic 和ISAP )
- 【POJ 3281 Dining】& 网络流Dinic & 拆点
- 拆点最大流-POJ-3281-Dining
- poj 3281 Dining(拆点+最大流)
- POJ---3281 Dining【拆点最大流】
- Dining poj 3281 拆点+
- POJ - 3281 Dining (ISAP EK Dinic)
- poj3281——Dining(网络流+拆点)
- POJ 3281 Dining 网络流
- POJ 3281 Dining(网络流)
- 【网络流】 POJ 3281 Dining
- poj 3281 Dining (网络流)
- 做文档专用:infoprovider提供的IO列表,和传输连接的列表(含ABAP代码)
- CE寻找游戏静态基址教程
- ubuntu 下 自定义python模块
- weblogic报<BEA-141281> <unable to get file lock, will retry …>
- 源码-PL/SQL从入门到精通-第十七章-面向对象编程-Part 2
- 网络流( ISAP + 拆点 )——Dining ( POJ 3281 )
- GDI+初始化类
- Android酷炫实用的开源框架(UI)
- 色彩空间转换
- Linux下查看系统版本号信息的方法
- Java的四种引用,强弱软虚,用到的场景
- 网络获取xml文件,pull解析listVist展示
- 多态实现线性表(队列,串,堆栈),要求具备线性表的基本操作
- Java工具箱之常见处理文件操作