TZOJ 5110 Pollutant Control(边数最少最小割最小字典序输出)
描述
It's your first day in Quality Control at Merry Milk Makers, and already there's been a catastrophe: a shipment of bad milk has been sent out. Unfortunately, you didn't discover this until the milk was already into your delivery system on its way to stores. You know which grocer that milk was destined for, but there may be multiple ways for the milk to get to that store.
The delivery system is made up of a several warehouses, with trucks running from warehouse to warehouse moving milk. While the milk will be found quickly, it is important that it does not make it to the grocer, so you must shut down enough trucks to ensure that it is impossible for the milk to get to the grocer in question. Every route costs a certain amount to shut down. Find the minimum amount that must be spent to ensure the milk does not reach its destination, along with a set of trucks to shut down that achieves this goal at that cost.
输入
Line 1: Two space separated integers, N and M. N (2 <= N <= 32) is the number of warehouses that Merry Milk Makers has, and M (0 <= M <= 1000) is the number of trucks routes run. Warehouse 1 is actually the productional facility, while warehouse N is the grocer to which which the bad milk was destined.
Line 2..M+1: Truck routes: three space-separated integers, Si, Ei, and Ci. Si and Ei (1 <= Si,Ei <= N) correspond to the pickup warehouse and dropoff warehouse for the truck route. Ci (0 <= Ci <= 2,000,000) is the cost of shutting down the truck route.
输出
The first line of the output should be two integers, C and T. C is the minimum amount which must be spent in order to ensure the our milk never reaches its destination. T is the minimum number of truck routes that you plan to shut down in order to achive this goal. The next T lines sould contain a sorted list of the indexes of the truck routes that you suggest shutting down. If there are multiple sets of truck routes that achieve the goal at minimum cost, choose one that shuts down the minimum number of routes. If there are still multiple sets, choose the one whose initial routes have the smallest index.
样例输入
4 5
1 3 100
3 2 50
2 4 60
1 2 40
2 3 80
样例输出
60 1
3
题意
N个点,M条有向边,求最小割,并且输出割了几条边,并且输出最小字典序。
题解
问题1就是个最小割。
问题2边数,相当于把边权哈希成w=w*1001+1,这样最小割%1001就是边数,而且可以保证边数最少。
问题3最小字典序,假设一条边是最小割集,那么删掉这条边w=w*1001+0后,最小割变小,若未变小则恢复这条边。
为什么删边不把w=0呢?(具体样例见代码最后)把w=0后,相当于把路断开了,最小割也变小了,但是不是我们需要的边。
根据最小割,边一定是路上的最小值,如果这条边是路上的最小值,那么你把w=w*1001+0后,最小割变小了。
如果这条边不是路上的最小值,那么你把w=w*1001+0后,最小割不变。
WA了两次一次w=0,一次忘记恢复了(忘记恢复就相当于自动把w=0了)。
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 #define LL long long 5 6 const int maxn=1e5+5; 7 const int maxm=2e5+5; 8 const int INF=0x3f3f3f3f; 9 10 int TO[maxm],NEXT[maxm],tote; 11 int FIR[maxn],gap[maxn],cur[maxn],d[maxn],q[400000]; 12 LL CAP[maxm],W[1005]; 13 int n,m,S,T; 14 int U[1005],V[1005]; 15 bool VIS[1005]; 16 17 void add(int u,int v,LL cap) 18 { 19 //printf("i=%d %d %d %d\n",tote,u,v,cap); 20 TO[tote]=v; 21 CAP[tote]=cap; 22 NEXT[tote]=FIR[u]; 23 FIR[u]=tote++; 24 25 TO[tote]=u; 26 CAP[tote]=0; 27 NEXT[tote]=FIR[v]; 28 FIR[v]=tote++; 29 } 30 void bfs() 31 { 32 memset(gap,0,sizeof gap); 33 memset(d,0,sizeof d); 34 ++gap[d[T]=1]; 35 for(int i=1;i<=n;++i)cur[i]=FIR[i]; 36 int head=1,tail=1; 37 q[1]=T; 38 while(head<=tail) 39 { 40 int u=q[head++]; 41 for(int v=FIR[u];v!=-1;v=NEXT[v]) 42 if(!d[TO[v]]) 43 ++gap[d[TO[v]]=d[u]+1],q[++tail]=TO[v]; 44 } 45 } 46 LL dfs(int u,LL fl) 47 { 48 if(u==T)return fl; 49 LL flow=0; 50 for(int &v=cur[u];v!=-1;v=NEXT[v]) 51 if(CAP[v]&&d[u]==d[TO[v]]+1) 52 { 53 LL Min=dfs(TO[v],min(fl,CAP[v])); 54 flow+=Min,fl-=Min,CAP[v]-=Min,CAP[v^1]+=Min; 55 if(!fl)return flow; 56 } 57 if(!(--gap[d[u]]))d[S]=n+1; 58 ++gap[++d[u]],cur[u]=FIR[u]; 59 return flow; 60 } 61 LL ISAP() 62 { 63 bfs(); 64 LL ret=0; 65 while(d[S]<=n)ret+=dfs(S,INF); 66 return ret; 67 } 68 void init() 69 { 70 tote=0; 71 memset(FIR,-1,sizeof FIR); 72 } 73 int main() 74 { 75 init(); 76 int N,M; 77 scanf("%d%d",&N,&M); 78 for(int i=1;i<=M;i++) 79 { 80 scanf("%d%d%lld",&U[i],&V[i],&W[i]); 81 add(U[i],V[i],W[i]*1001+1); 82 VIS[i]=1; 83 } 84 S=1,T=N,n=T; 85 LL ans=ISAP(); 86 printf("%lld %lld\n",ans/1001,ans%1001); 87 for(int i=1;i<=M;i++) 88 { 89 init(); 90 VIS[i]=0; 91 for(int j=1;j<=M;j++) 92 add(U[j],V[j],W[j]*1001+VIS[j]); 93 LL bns=ISAP(); 94 if(bns<ans) 95 { 96 ans=bns; 97 printf("%d\n",i); 98 } 99 else 100 VIS[i]=1; 101 //printf("i=%d %lld %lld\n",i,bns/1001,bns%1001); 102 } 103 return 0; 104 } 105 /* 106 5 5 107 2 4 30 108 1 2 30 109 4 5 40 110 1 3 50 111 3 5 30 112 */
原文地址:https://www.cnblogs.com/taozi1115402474/p/11765104.html
- 用linqPad帮助你快速学习LINQ
- Java 8 Stream 教程 (二)
- CountVectorizer
- Caliburn.Micro学习笔记(五)----协同IResult
- 一个Pythoner的自我修养系列(一)
- 众里寻她千百度,蓦然回首,那bug却在灯火阑珊处
- Github|Python开源项目漫游指南(一)
- Caliburn.Micro学习笔记(四)----IHandle<T>实现多语言功能
- .NET 4 System.Threading.CountdownEvent
- java与ruby的直观比较
- 每天一个Linux命令:chmod
- SparkSql 中外连接查询中的谓词下推规则
- Caliburn.Micro学习笔记(三)----事件聚合IEventAggregator和 Ihandle<T>
- Python进行数据可视化分析快速教程实例
- 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 数组属性和方法