UVA 10480 Sabotage (最大流)
时间:2019-11-11
本文章向大家介绍UVA 10480 Sabotage (最大流) ,主要包括UVA 10480 Sabotage (最大流) 使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题意:
编写一个程序,给定一个网络规范和破坏每个连接的成本,确定要切断哪个连接,以便将首都和最大的城市分离到尽可能低的成本。
输入:
输入文件包含几组输入。每一组的描述如下。每个集合的第一行有两个整数,用空格隔开:第一个是网络中的城市数量n,最多为50。第二个是连接的总数,m,最多500。以下m行指定连接。每条线由三部分组成,中间用空格隔开:前两部分是由这两部分连接起来的城市(数字在1 - n范围内)。然后是切断连接的成本(范围为1到40000000的整数)。在这个列表中,每对引用最多只能出现一次。当n和m的值为0时,输入终止。这种情况不应该处理。对于每个输入集,首都是第1个城市,最大的城市是第2个城市。
输出:
对于每个输入集,您应该生成几行输出。每个输入集的输出描述如下:每个输入集的输出应该是城市对(即数字),它们之间的连接应该被切断(以任何顺序),每对在一行,数字之间用空格隔开。如果有多个解决方案,任何一个都可以。在每个输入集的输出之后打印空行。
题解:
1 void addedge(int u, int v, int w) //建双向边 2 { //u为起点,v为终点,w为边上的流量 3 edge[tot].v = v; 4 edge[tot].w = w; 5 edge[tot].next = head[u]; 6 head[u] = tot++; 7 8 edge[tot].v = u; 9 edge[tot].w = w; 10 edge[tot].next = head[v]; 11 head[v] = tot++; 12 return; 13 }
我之前就有一个疑问就是,为什么在建有向边的时候还要建一条容量为0的反向边。
其实这就是为了反悔之前的操作,因为我们第一次跑最大流的时候肯定会有好多路都可以跑到终点。但是我们最后要的是最大流,这就要考虑到最优策略,所以我们之前走过的路可能要改变。这个时候建立反向边的作用就体现了
代码:
//本题是可以双向走,那么我们正向也可以反向也可以,所以我们在建反向边的时候就不能给它初始值为0,因为 //他刚开始反向边就可以走 //在最后一次bfs之后,肯定就会出现断层(即,到不了终点),这个时候因为中间出现了流量为0所以到不了, //那么这些流量为0就是我们删去的边 #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<queue> using namespace std; const int maxn=10005; const int INF=0x3f3f3f3f; int head[maxn],cnt,st,en,dis[maxn],cur[maxn],xx[maxn],yy[maxn]; struct edge { int v,next,c,flow; } e[100005]; void add_edge(int x,int y,int z) { e[cnt].v=y; e[cnt].c=z; e[cnt].flow=0; e[cnt].next=head[x]; head[x]=cnt++; } bool bfs() { memset(dis,0,sizeof(dis)); dis[st]=1; queue<int>r; r.push(st); while(!r.empty()) { int x=r.front(); r.pop(); for(int i=head[x];i!=-1;i=e[i].next) { int v=e[i].v; if(!dis[v] && e[i].c>e[i].flow) { dis[v]=dis[x]+1; r.push(v); } } } return dis[en]; } int dinic(int s,int limit) { if(s==en || !limit) return limit; int ans=0; for(int &i=cur[s];i!=-1;i=e[i].next) { int v=e[i].v,feed; if(dis[v]!=dis[s]+1) continue; feed=dinic(v,min(limit,e[i].c-e[i].flow)); if(feed) { e[i].flow+=feed; e[i^1].flow-=feed; limit-=feed; ans+=feed; if(limit==0) break; } } if(!ans) dis[s]=-1; return ans; } int main() { int s,d,n,m; while(~scanf("%d%d",&n,&m) && n+m) { memset(head,-1,sizeof(head)); cnt=0; st=1; en=2; int x,y,z; for(int i=1;i<=m;++i) { scanf("%d%d%d",&x,&y,&z); xx[i]=x; yy[i]=y; add_edge(x,y,z); add_edge(y,x,z); } int ans=0; while(bfs()) { for(int i=0; i<=n; i++) cur[i]=head[i]; ans+=dinic(st,INF); } for(int i=1;i<=m;++i) { if((!dis[xx[i]] && dis[yy[i]]) || (dis[xx[i]] && !dis[yy[i]])) { printf("%d %d\n",xx[i],yy[i]); } } printf("\n"); } return 0; }
原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/11837866.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 学了这个,三歪再也不想写各种setter了
- 使用 GitLab CI 与 Argo CD 进行 GitOps 实践
- Java 语言中十大“坑爹”功能!
- 面试:说说啥是一致性哈希算法?
- 问一下,线程池里面到底该设置多少个线程?
- 进程和线程基础知识全家桶,30 张图一套带走
- Python-matplotlib 学术柱状图绘制
- 为什么要避免大事务以及大事务如何解决?
- [即时通信IM]群@消息如何实现?
- 利用PySpark对 Tweets 流数据进行情感分析实战
- ConcurrentHashMap源码学习
- HashMap源码学习
- Pytest自动化测试fixture之conftest.py
- ArrayList源码学习
- 科技将带给我们什么变化?讲述基于 HTML5 WebGL 的 3D 科幻风机