网络流(最小割最大流(记录路径))【POJ1815】
来源:互联网 发布:java培训机构排名2016 编辑:程序博客网 时间:2024/05/21 08:37
【POJ1815】
出处:原帖
题意:就是求s点到t点,最少去掉几个点使得他们不连通。如果无解输出NO ANSWER!
解题思路 因为最小割只能求割掉几条边的解,我们要求的是割掉几个点。那么我们可以这样考虑:把每个点拆成入点和出点。入点->出点权值为1。那么割掉这条边就相当于割掉这个点了,就能把这题转化成最小割。那么原来的边,我们是不希望去割它的,所以我们将原来的边的权值设置为INF。例如,原来边为u->v那么就变成out(u)->in(v)。这样跑一次最大流,跑出来的答案就是最小割掉的点数。这题还要我们求出一个点集,就是割掉的点,按字典序排列。因为割点可能会有多种组合,所以最简单的思路就是枚举。如果这个点割掉之后,跑出来的答案能少割一个点,那么这个点就是要求的点之一,割掉它,继续枚举,一直到枚举出所有答案为止。
应该还有不枚举的更好方法,求教学。。。
代码:
#include<cstdio>#include<cstring>#include<string>#include<queue>#include<map>#include<iostream>#include<vector>#include<cstdlib>#include<cmath>#include<stack>#include<cctype>#include<set>#include<ctime>#include<cassert>#include<algorithm>using namespace std;typedef long long ll;const int INF=1e9+7;typedef pair<int,int> pii;#define MP make_pair#define PB push_back#define in(x) (x)#define out(x) (x+n)int n,st,ed;int start[210][210],pic[555][555],d[555];bool del[555];vector<int> pr;void build(){ for(int i=1;i<=n;i++){ if(!del[i]) pic[in(i)][out(i)]=1;//拆点,后面枚举了割掉的点,所以用del数组标记 //容量是1,希望在割边的时候割它,割掉点中的边相当于割点,就把最小割转化成割点了 } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++)if(start[i][j]){ pic[out(i)][in(j)]=INF; //割这条边的流量是INF,意味着不希望去割它 } }}bool BFS(){ queue<int> Q; memset(d,-1,sizeof d); Q.push(st);d[st]=0; while(!Q.empty()){ int s=Q.front();Q.pop(); for(int i=1;i<=n+n;i++){ if(pic[s][i]>0&&d[i]<0){ d[i]=d[s]+1;if(i==ed)return true; Q.push(i); } } } return false;}int DFS(int s,int t,int flow){ if(s==t||flow==0)return flow; int ans=0; for(int i=1;i<=n+n;i++){ if(d[i]==d[s]+1&&pic[s][i]>0){ int ff=DFS(i,t,min(pic[s][i],flow)); if(ff>0){ pic[s][i]-=ff; pic[i][s]+=ff; ans+=ff; flow-=ff; if(!flow)break; } } } if(!ans)d[s]=-1; return ans;}int dinic(){ int ans=0; while(BFS()){ ans+=DFS(st,ed,INF); } return ans;}int main(){// freopen("D://input.txt","r",stdin); scanf("%d%d%d",&n,&st,&ed); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ scanf("%d",&start[i][j]); } } if(start[st][ed]){printf("NO ANSWER!\n");return 0;} //只有直接相连的时候会无解 st=out(st);ed=in(ed); build(); int ans=dinic(); printf("%d\n",ans); if(!ans)return 0; for(int i=1;i<=n;i++){ //因为割点可能会有很多组合,而且要求字典序最小,所以只能割一个就标记上,一直到割完为止 if(i==st-n||i==ed)continue; del[i]=true; build(); int t=dinic(); if(t<ans){ ans--;pr.PB(i); if(ans==0)break; } else del[i]=false;; } for(int i=0;i<(int)pr.size();i++){ if(i)printf(" "); printf("%d",pr[i]); } printf("\n"); return 0;}
1 0
- 网络流(最小割最大流(记录路径))【POJ1815】
- 【POJ1815】Friendship 网络流最小割
- 最小割最大流记录
- 网络流(最小割最大流)【POJ3469】
- 网络流(最小割最大流)【POJ3308】
- 网络流(最大流,最小割)基础入门详解
- 求最大网络流(最小割)总结
- hihoCoder 1378 网络流二·最大流最小割定理 (网络流学习#2 记录)
- 网络流最大流最小割算法
- 网络流最大流最小割算法
- 网络流 最小割最大流定理
- 网络的最大流最小割定理
- poj 3469(最大流最小割)
- 最大流最小割(概念)
- Dinic模板(最大流最小割)
- dinic最大流模板(最小割)
- 【网络流】最大流:求最小割值、求(边)不交路径数量、求二分匹配最大匹配数
- [网络流24题] 24 骑士共存(二分图最大独立集,网络最小割)
- 概念定义
- Android开发之Context的使用
- java 裁剪图片 参数 宽 高 自动按照比例来剪切
- 单例模式多线程下可行的方案
- 关于JavaFX拓展控件库ControlsFx的AutoCompletionBinding的使用
- 网络流(最小割最大流(记录路径))【POJ1815】
- ARM寄存器一览
- fragment和radiobutton做出类tabhost效果
- C语言实现栈(基于链表)
- 思绪整理
- opencv 3.0安装时提示ippicv 安装的MD5不匹配问题
- ubuntu系统安装nginx
- Java中有关Char的学习笔记
- 深入分析 Java 中的中文编码问题