博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ 3281 Dining 【最大流】【神建模】
阅读量:5348 次
发布时间:2019-06-15

本文共 2240 字,大约阅读时间需要 7 分钟。

这个思路是真的想不到。

一开始想的是源点到每个奶牛的容量为1,然后奶牛到drink和food可以建容量为1的边,但怎么连到汇点就不知道了。

神来之笔是,把源点跟所有food连边,然后food跟输入指定的奶牛连边,奶牛再按输入跟drink连边,所有drink再去跟汇点连边。【特定奶牛吃了food,再喝drink,再流到汇点 与 任意奶牛吃任意food,然后变成特定奶牛,然后喝指定drink,再到汇点是一回事!】

但这么做不对,因为我们还要保证每个奶牛为答案的贡献不超过1,所以要把【一个奶牛拆成两个】,所以是源->food->奶牛(左)->奶牛(右)->drink->汇。

 

拿vector实现了一次,这样的话网络流的所有实现方法我都写过一遍了

#include
#include
#include
#include
#define INF 2e9using namespace std;int N,F,D,T;struct edge{ int v,cap,reverse;};vector
edges[1005];//邻接表 vector
bian;//所有的边都存在里面 void addedge(int u,int v,int cap){ //u到v一条边,再加一条反向边 edge e; e.cap=cap; e.v=v; e.reverse=bian.size()+1;//这条边的反边将建在这条边之后(这条边建完后在bian.size()的位置) bian.push_back(e); edges[u].push_back(bian.size()-1); e.cap=0; e.v=u; e.reverse=bian.size()-1; bian.push_back(e); edges[v].push_back(bian.size()-1);}int layer[1005],vis[1005];bool count_layer(){ memset(layer,0,sizeof(layer)); deque
q; layer[0]=1; q.push_back(0); while( !q.empty() ){ int u = q.front(); q.pop_front(); if( u==T ) return true; for(int i=0;i
0 ){ layer[v] = layer[u] + 1; q.push_back( v ); } } } return false;}int dinic(){ int max_flow=0; while( count_layer() ){ memset(vis,0,sizeof(vis)); deque
q,path;//记录一路走过来的【点】和【边的索引】 q.push_back(0); vis[0]=1; while(!q.empty()){ int u = q.back(); if( u==T ){ int min_u,min_v,min_flow=INF; int p=0;//从0点出发 for(int i=0;i
0 ){ vis[e.v]=1; q.push_back( e.v ); path.push_back( edges[u][i] ); break; } } if(i==edges[u].size()) { q.pop_back(); path.pop_back(); } } } } return max_flow;}int main(){ //food编号1 - F //把一头牛拆成两头 //cows1编号F+1 - F+N //cows2编号F+N+1 - F+N+N //drink编号F+2N+1 - F+2N+D cin>>N>>F>>D; T=N+N+F+D+1; for(int i=1;i<=N;i++){ int fi,di,food,drink; cin>>fi>>di; for(int j=1;j<=fi;j++) cin>>food,addedge(food,F+i,1);//food到奶牛1建一条边 for(int j=1;j<=di;j++) cin>>drink,addedge(F+N+i,F+2*N+drink,1);//从奶牛2到drink建一条边 } for(int i=F+1;i<=F+N;i++) addedge(i,i+N,1);//奶牛1到奶牛2建一条边 for(int i=1;i<=F;i++) addedge(0,i,1);//从源点0到所有food建边 for(int i=F+2*N+1;i<=F+2*N+D;i++) addedge(i,T,1); //从所有drink到汇点F+D+2*N+1建边 cout<

 

转载于:https://www.cnblogs.com/ZhenghangHu/p/9521288.html

你可能感兴趣的文章
字母和数字键的键码值(keyCode)
查看>>
IE8调用window.open导出EXCEL文件题目
查看>>
Spring mvc初学
查看>>
有意思的代码片段
查看>>
C8051开发环境
查看>>
VTKMY 3.3 VS 2010 Configuration 配置
查看>>
01_1_准备ibatis环境
查看>>
windows中修改catalina.sh上传到linux执行报错This file is needed to run this program解决
查看>>
JavaScript中的BOM和DOM
查看>>
360浏览器兼容模式 不能$.post (不是a 连接 onclick的问题!!)
查看>>
spring注入Properties
查看>>
【BZOJ-1055】玩具取名 区间DP
查看>>
Bit Twiddling Hacks
查看>>
LeetCode : Reverse Vowels of a String
查看>>
时间戳与日期的相互转换
查看>>
jmeter(五)创建web测试计划
查看>>
python基本数据类型
查看>>
1305: [CQOI2009]dance跳舞 - BZOJ
查看>>
关于TDD的思考
查看>>
Cocos2d-x学习之windows 7 android环境搭建
查看>>