poj 3281
来源:互联网 发布:淘宝联盟是骗局吗 编辑:程序博客网 时间:2024/06/15 06:12
题意:给出牛,饮料还有食物的数量,每头牛给出喜欢的饮料和食物,最后求出能够满足的牛的数量
戳
一开始觉得是二分图匹配,但是怎么配两边的呢?
遂放弃。
然后 听说网络流可以弄二分图?
很好。怎么解决 一头牛对应一种呢?把牛拆成;两个点,中间连一条边权为1的边。
搞定。那现在说一下EK算法。
戳这里就好
给个模板题 1273
#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;const int VM=220;const int INF=0x3f3f3f3f;int n,m,max_flow; //max_flow是最大流int map[VM][VM],flow[VM][VM]; // map[i][j]是每条边的容量,flow[i][j]是每条边的流量 int res[VM],pre[VM]; //res[]是每个点的剩余流量,pre[]是每个点的父亲int EK(int src,int des){ max_flow=0; queue<int> q; while(!q.empty()) q.pop(); memset(flow,0,sizeof(flow)); //最开始每条边的流量都是0 while(1){ memset(res,0,sizeof(res)); //残余流量得变0,一开始所有点都没流入对吧 res[src]=INF; //源点嘛,剩余流量无限是必须的... q.push(src); //从源点开始进行BFS找增广路 int u,v; while(!q.empty()){ u=q.front(); q.pop(); for(v=1;v<=m;v++) //遍历所有点,找可行边 if(!res[v] && map[u][v]>flow[u][v]){ //该点剩余流量为0 且 容量大于流量,也就是找到了新的结点 pre[v]=u; //找到新结点,父节点得记录一下吧 q.push(v); res[v]=min(res[u],map[u][v]-flow[u][v]); //如果u的剩余流量能填满uv就填满,不能的话就把u这点的流量全部流向uv } } if(res[des]==0) //如果当前已经是最大流,汇点没有残余流量 return max_flow; for(u=des;u!=src;u=pre[u]){ //如果还能增广,那么回溯,从汇点往回更新每条走过的边的流量 flow[pre[u]][u]+=res[des]; //更新正向流量 (注意这里更新的是流量,而不是容量) flow[u][pre[u]]-=res[des]; //更新反向流量 } max_flow+=res[des]; }}int main(){ while(~scanf("%d%d",&n,&m)){ memset(map,0,sizeof(map)); memset(pre,0,sizeof(pre)); int u,v,w; while(n--){ scanf("%d%d%d",&u,&v,&w); map[u][v]+=w; //有重边 } printf("%d\n",EK(1,m)); } return 0;}
所以这道题为什么WA了一次
因为 我没有建后向边,也就是凡是有一条正向的这样的边都要建一条反向的边权为0的边来退流!!!!
推流!!!不然时挂的!!
1.对算法本身并没有吃透
2.建边的技巧
#include<cstdio>#include<algorithm>#include<cstring>#include<queue>#define inf 0x3fffffff//by mars_chusing namespace std;int n,f,d; struct data{ int f,t,nxt,c;}e[100005];int tot,first[605];int flow[605][605];int pre[605],res[605];void add(int a,int b,int c){ e[tot].f=a; e[tot].t=b; e[tot].c=c; e[tot].nxt=first[a]; first[a]=tot++;}int EK(int s,int end){ queue<int> q; int max_flow=0; while(1) { memset(res,0,sizeof(res)); res[s]=inf; q.push(s); while(!q.empty()) { int t=q.front(); q.pop(); for(int j=first[t];j!=-1;j=e[j].nxt) { int v=e[j].t; if(!res[v] && e[j].c>flow[t][v]) { pre[v]=t; q.push(v); res[v]=min(res[t],e[j].c-flow[t][v]); } } } if(res[end] == 0) { return max_flow; } for(int i=end;i!=s;i=pre[i]) { flow[pre[i]][i]+=res[end]; flow[i][pre[i]]-=res[end]; } max_flow+=res[end]; }}int main(){ memset(first,-1,sizeof(first)); scanf("%d%d%d",&n,&f,&d); int s=f+2*n+d+1; for(int i=1;i<=f;i++) { add(0,i,1); add(i,0,0); } for(int i=f+1;i<=f+n;i++) { add(i,i+n,1); add(i+n,i,0); } for(int i=f+2*n+1;i<=f+2*n+d;i++) { add(i,s,1); add(s,i,0); } for(int i=1;i<=n;i++) { int a,b; scanf("%d%d",&a,&b); for(int j=1;j<=a;j++) { int x; scanf("%d",&x); add(x,i+f,1); add(i+f,x,0); } for(int j=1;j<=b;j++) { int x; scanf("%d",&x); add(i+n+f,x+f+2*n,1); add(x+f+2*n,i+n+f,0); } } int ans=EK(0,s); printf("%d\n",ans); return 0;}
0 0
- poj 3281
- POJ 3281
- poj 3281
- poj 3281
- POJ 3281
- poj 3281
- poj 3281
- poj 3281 Dining Maxflow
- POJ 3281 Dining
- poj 3281 Dining //SAP
- POJ 3281 Dining
- poj 3281 Dining
- poj 3281 Dining
- POJ 3281 Dining
- POJ 3281 Dining
- poj 3281 Dining
- poj 3281 最大流
- POJ-3281-Dining
- Java 8 in Action (1) -- 函数式接口
- 第七周项目2——建立链队算法库
- 算术运算
- OOAD基本概念
- poj 2367 Genealogical tree(DAG的拓扑排序)
- poj 3281
- 【1】Android Service
- 翻转单词顺序列 java
- SPOJ 694 / SPOJ DISUBSTR Distinct Substrings【后缀数组】不相同的子串的个数
- 浅谈人工智能
- 1066. Root of AVL Tree (25)
- 剑指Offer面试题44:扑克牌的顺子 Java实现
- nodejs使用asyn优化的爬取
- Java笔记 - 多线程-单例设计模式