POJ 3281 网络流(dinic邻接矩阵、单路增广、多路增广)
来源:互联网 发布:淘宝网微淘入口 编辑:程序博客网 时间:2024/04/29 13:45
思路:刚开始看题就想到怎么建图了,源点连向所有的食物,食物连牛,牛连饮料,饮料连汇点,所有的流量都是1.不过这样建图好后,WA了。原来是一头牛只能单一匹配一组食物和饮料,所以牛得拆点,牛之间得相连,流量为1,以保证单一匹配食物和饮料。
邻接矩阵dinic单路的代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<map>#include<queue>#include<set>#include<cmath>#include<bitset>#define mem(a,b) memset(a,b,sizeof(a))#define lson i<<1,l,mid#define rson i<<1|1,mid+1,r#define llson j<<1,l,mid#define rrson j<<1|1,mid+1,r#define INF 0x7fffffff#define maxn 20005typedef long long ll;typedef unsigned long long ull;using namespace std;int n,m,d[maxn],Map[501][501];int bfs(){ mem(d,-1); queue<int>q; q.push(0); d[0]=0; while(!q.empty()) //找增广路 { int u=q.front(); q.pop(); for(int v=0;v<=n;v++) { if(d[v]==-1&&Map[u][v]) { d[v]=d[u]+1; //分层,越往后,层数越大 q.push(v); } } } return d[n]!=-1;}int dfs(int u,int Min){ int sum; if(u==n) return Min; for(int v=0;v<=n;v++) if(Map[u][v]&&d[v]==d[u]+1&&(sum=dfs(v,min(Min,Map[u][v])))) { Map[u][v]-=sum; Map[v][u]+=sum; return sum; } return 0;}int Dinic(){ int tmp,ans=0; while(bfs()) { while(tmp=dfs(0,INF)) ans+=tmp; } return ans;}int main(){ //freopen("1.txt","r",stdin); int N,F,D,ff,dd,i,j,mm; scanf("%d%d%d",&N,&F,&D); for(i=1;i<=N;i++) { scanf("%d%d",&ff,&dd); for(j=0;j<ff;j++) { scanf("%d",&mm); Map[mm+N*2][i]=1; } for(j=0;j<dd;j++) { scanf("%d",&mm); Map[i+N][mm+N*2+F]=1; } Map[i][i+N]=1;//牛之间自连,保存每头牛只匹配一组食物和饮料 } for(i=N*2+1;i<=N*2+F;i++) Map[0][i]=1;//连源点 n=N*2+F+D+1; for(i=N*2+F+1;i<=N*2+F+D;i++) Map[i][n]=1;//连汇点 printf("%d\n",Dinic()); return 0;}dinic单路增广代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<map>#include<queue>#include<set>#include<cmath>#include<bitset>#define mem(a,b) memset(a,b,sizeof(a))#define lson i<<1,l,mid#define rson i<<1|1,mid+1,r#define llson j<<1,l,mid#define rrson j<<1|1,mid+1,r#define INF 0x7ffffffftypedef long long ll;typedef unsigned long long ull;using namespace std;#define maxn 2000005int n,cnt,d[maxn],head[maxn],go[maxn],q[maxn];struct node{ int v,w,next;}e[maxn];void add(int u,int v,int w){ e[cnt].v=v; e[cnt].w=w; go[cnt]=cnt+1; e[cnt].next=head[u]; head[u]=cnt++; e[cnt].v=u; e[cnt].w=0; go[cnt]=cnt-1;//刚开始反向边权值写成w了一直wa e[cnt].next=head[v]; head[v]=cnt++;}int bfs(){ mem(d,-1); int l=0,r=0; q[r++]=0; d[0]=0; while(l<r) //找增广路 { int u=q[l++]; for(int v=head[u];v!=-1;v=e[v].next) { if(d[e[v].v]==-1&&e[v].w) { d[e[v].v]=d[u]+1; //分层,越往后,层数越大 if(e[v].v!=n+1) q[r++]=e[v].v; } } } return d[n]!=-1;}int dfs(int u,int Min){ int sum; if(u==n) return Min; for(int v=head[u];v!=-1;v=e[v].next) //Min-duolu这个多路增广的做法真神! if(e[v].w&&d[e[v].v]==d[u]+1&&(sum=dfs(e[v].v,min(Min,e[v].w)))) { e[v].w-=sum; e[go[v]].w+=sum; return sum; } return 0;}void init(){ mem(head,-1),mem(go,0),cnt=0;}int Dinic(){ int tmp,ans=0; while(bfs()) { while(tmp=dfs(0,INF)) ans+=tmp; } return ans;}int main(){ //freopen("1.txt","r",stdin); int N,F,D,ff,dd,i,j,mm; scanf("%d%d%d",&N,&F,&D); init(); for(i=1;i<=N;i++) { scanf("%d%d",&ff,&dd); for(j=0;j<ff;j++) { scanf("%d",&mm); add(mm+N*2,i,1); } for(j=0;j<dd;j++) { scanf("%d",&mm); add(i+N,mm+N*2+F,1); } add(i,i+N,1);//牛之间自连,保存每头牛只匹配一组食物和饮料 } for(i=N*2+1;i<=N*2+F;i++) add(0,i,1);//连源点 n=N*2+F+D+1; for(i=N*2+F+1;i<=N*2+F+D;i++) add(i,n,1);//连汇点 printf("%d\n",Dinic()); return 0;}Dinic多路增广代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<map>#include<queue>#include<set>#include<cmath>#include<bitset>#define mem(a,b) memset(a,b,sizeof(a))#define lson i<<1,l,mid#define rson i<<1|1,mid+1,r#define llson j<<1,l,mid#define rrson j<<1|1,mid+1,r#define INF 0x7ffffffftypedef long long ll;typedef unsigned long long ull;using namespace std;#define maxn 2000005int n,cnt,d[maxn],head[maxn],go[maxn],q[maxn];struct node{ int v,w,next;}e[maxn];void add(int u,int v,int w){ e[cnt].v=v; e[cnt].w=w; go[cnt]=cnt+1; e[cnt].next=head[u]; head[u]=cnt++; e[cnt].v=u; e[cnt].w=0; go[cnt]=cnt-1;//刚开始反向边权值写成w了一直wa e[cnt].next=head[v]; head[v]=cnt++;}int bfs(){ mem(d,-1); int l=0,r=0; q[r++]=0; d[0]=0; while(l<r) //找增广路 { int u=q[l++]; for(int v=head[u];v!=-1;v=e[v].next) { if(d[e[v].v]==-1&&e[v].w) { d[e[v].v]=d[u]+1; //分层,越往后,层数越大 if(e[v].v!=n+1) q[r++]=e[v].v; } } } return d[n]!=-1;}int dfs(int u,int Min){ int sum,duolu=0; if(u==n) return Min; for(int v=head[u];v!=-1&&Min-duolu>0;v=e[v].next) //Min-duolu这个多路增广的做法真神! if(e[v].w&&d[e[v].v]==d[u]+1&&(sum=dfs(e[v].v,min(Min-duolu,e[v].w)))) { e[v].w-=sum; e[go[v]].w+=sum; duolu+=sum; } return duolu;}void init(){ mem(head,-1),mem(go,0),cnt=0;}int Dinic(){ int tmp,ans=0; while(bfs()) { while(tmp=dfs(0,INF)) ans+=tmp; } return ans;}int main(){ //freopen("1.txt","r",stdin); int N,F,D,ff,dd,i,j,mm; scanf("%d%d%d",&N,&F,&D); init(); for(i=1;i<=N;i++) { scanf("%d%d",&ff,&dd); for(j=0;j<ff;j++) { scanf("%d",&mm); add(mm+N*2,i,1); } for(j=0;j<dd;j++) { scanf("%d",&mm); add(i+N,mm+N*2+F,1); } add(i,i+N,1);//牛之间自连,保存每头牛只匹配一组食物和饮料 } for(i=N*2+1;i<=N*2+F;i++) add(0,i,1);//连源点 n=N*2+F+D+1; for(i=N*2+F+1;i<=N*2+F+D;i++) add(i,n,1);//连汇点 printf("%d\n",Dinic()); return 0;}
0 0
- POJ 3281 网络流(dinic邻接矩阵、单路增广、多路增广)
- 网络流DINIC增广路算法介绍
- POJ 3469 第一次AC总结(Dinic+多路增广)
- 【网络流】【更新模板】dinic多路增广+当前弧
- poj 3469 Dual Core CPU 网络流最小割,dinic多路增广
- POJ 3469最大流最小割原理(Dinic多路增广)
- 模板---图论:网络流增广路算法 Dinic
- 网络最大流增广路模板(EK & Dinic)
- 网络流增广路Edmonds-Karp算法 与 Dinic算法
- dinic模板 当前弧+多路增广
- kyeremal-最大流dinic算法模板-多路增广
- 模板:DINIC(多路增广)+当前弧优化
- 网络流,增广路,Edmonds_Karp 以及 Dinic 算法(HDU 1532)
- (dinic增广网络流模板)(sizeof用法)poj-3469-Dual Core CPU
- 2016-8-9夏令营总结(网络流—增广路+dinic)
- poj 1459 最大流增广路算法
- 基于增广路的网络流算法
- 网络流之增广路算法
- 创建一个Qt Quick UI project
- ios 常用加密算法
- struts2 <debug>标签报错:Caught an exception while getting the property values of null
- Java命名规则
- centos升级python
- POJ 3281 网络流(dinic邻接矩阵、单路增广、多路增广)
- android消息推送概述
- UIDatePickerView实现时间滚动轮播效果
- RPC应用的java实现
- Oracle中SQL语句学习六((连接查询)
- 加密和解密采用不同的密钥
- Android4.x 如何处理Power按键
- Java中,检查list及其元素是否为空
- 在Oracle数据库软件中的各种错误提示前缀所属的软件层次