描述 Description
你第一天接手三鹿牛奶公司就发生了一件倒霉的事情:公司不小心发送了一批有三聚氰胺的牛奶。很不幸,你发现这件事的时候,有三聚氰胺的牛奶已经进入了送货网。这个送货网很大,而且关系复杂。你知道这批牛奶要发给哪个零售商,但是要把这批牛奶送到他手中有许多种途径。送货网由一些仓库和运输卡车组成,每辆卡车都在各自固定的两个仓库之间单向运输牛奶。在追查这些有三聚氰胺的牛奶的时候,有必要保证它不被送到零售商手里,所以必须使某些运输卡车停止运输,但是停止每辆卡车都会有一定的经济损失。你的任务是,在保证坏牛奶不送到零售商的前提下,制定出停止卡车运输的方案,使损失最小。
输入格式 Input Format
第一行: 两个整数N(2<=N<=32)、M(0<=M<=1000), N表示仓库的数目,M表示运输卡车的数量。仓库1代 表发货工厂,仓库N代表有三聚氰胺的牛奶要发往的零售商。 第2..M+1行: 每行3个整数Si,Ei,Ci。其中Si,Ei表示这 辆卡车的出发仓库,目的仓库。Ci(0 <= C i <= 2,000,000) 表示让这辆卡车停止运输的损失。
输出格式 Output Format
第1行两个整数c、t,c表示最小的损失,T表示要停止的最少卡车数。接下来t 行表示你要停止哪几条线路。如果有多种方案使损失最小,输出停止的线路最少的方案。如果仍然还有相同的方案,请选择开始输入顺序最小的。
样例输入 Sample Input

4 5
1 3 100
3 2 50
2 4 60
1 2 40
2 3 80

样例输出 Sample Output

60 1
3

时间限制 Time Limitation
1s
注释 Hint
1s
来源 Source
usaco 4.4.2

不得不说这道题真的是毒,输出最小割,割的边数,以及割的方案。

因为只有1000条边,我们将每条边的流量*1001+1,求出最大流后/1001即是最大流【相信能理解】,%1001之后就是割的边数【这也很好理解】。

  最难的第三个问题:输出割的方案。虽然可以通过:枚举每条边,先去掉这条边,然后再求最大流,如果最大流的减小值是这条边的权值,那么这条边就在内,输出即可。然而虽然数据量支持我们这么做,但是OJ的数据..........1000条1到4的边,流量都是2000000。虽然可以在评测姬变卡之后仍能过去【gy0.7s此点】,但是写的不知道为什么我自己本地0.9s。但是发现树神有更高级的写法:

  从源点进行DFS遍历,如果到下一条边流量不为0,继续遍历标记。最后对于每个点枚举它的边,如果x到y有边,x标记,y为标记,说明这条边在最小割中。然而OJ是有数据卡这个方法的。这个方法求的边是第一个遇到的最小割,然而如果1 2 3 4四个点,之间流量都是10,边如下:3 4 10,2 3 10,1 2 10。因为题目要求给出多种方法,按边的序号字典序输出,这四个点割一条边,肯定是都可以的,正解是输出1【3 4这条边,序号为1】。但是图中按此法显然我们求出的是1 ,2。

  我们便可以发现问题了。但是这种数据只能用来卡序号,这就需要此方法求得的这条边能导致后面不连通。那么显然这条边流量是满的。后面如果出现更优解【字典序更小】,那么也必须流量是满的,且流量一样,并满足边数等于前面。

   但是,这也并不是正解,仍然会被卡掉。正解还是删边求最大流。

  错误但能水过的代码:

  1. #include<bits/stdc++.h>
  2. #define ll long long
  3. #define INF 2100000000
  4. using namespace std;
  5. int level[];
  6. int q[];
  7. int lin[];
  8. int rev[];
  9. bool f[];
  10. bool fe[];
  11. int len=;
  12. ll ans=;
  13. int cnt[];
  14. struct www
  15. {
  16. ll v;
  17. int id;
  18. }a[][],b[][],c[];
  19. ll n,m;
  20. ll s,t;
  21. struct qaq{
  22. int nt,y;
  23. ll v;
  24. }e[];
  25.  
  26. char buf[<<],*fs,*ft;
  27. inline char getc(){ return(fs==ft && (ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++; }
  28. ll read()
  29. {
  30. ll x=;
  31. char ch=getc();
  32. while(!isdigit(ch)) ch=getc();
  33. while(isdigit(ch)) {x=(x<<)+(x<<)+ch-''; ch=getc();}
  34. return x;
  35. }
  36.  
  37. void insert(int x,int y,ll v)
  38. {
  39. e[++len].nt=lin[x]; e[len].v=v; e[len].y=y; lin[x]=len; rev[len]=len+; fe[len]=;
  40. e[++len].nt=lin[y]; e[len].v=; e[len].y=x; lin[y]=len; rev[len]=len-;
  41. }
  42.  
  43. bool make_level()
  44. {
  45. ll head=,tail=;
  46. memset(level,-,sizeof(level));
  47. q[]=s;level[s]=;
  48. while(head++<tail)
  49. {
  50. ll x=q[head];
  51. for(ll i=lin[x];i;i=e[i].nt)
  52. if(e[i].v && level[e[i].y]==-)
  53. {
  54. level[e[i].y]=level[x]+;
  55. q[++tail]=e[i].y;
  56. }
  57. }
  58. return level[t]>=;
  59. }
  60.  
  61. ll max_flow(ll k,ll flow)
  62. {
  63. if(k==t) return flow;
  64. ll maxflow=;
  65. ll v;
  66. for(ll i=lin[k];i && (maxflow<flow);i=e[i].nt)
  67. if(e[i].v && level[e[i].y]==level[k]+)
  68. if(v=max_flow(e[i].y,min(e[i].v,flow-maxflow)))
  69. maxflow+=v,e[i].v-=v,e[rev[i]].v+=v;
  70. if(!maxflow) level[k]=-;
  71. return maxflow;
  72. }
  73.  
  74. ll dinic()
  75. {
  76. ans=;
  77. ll v;
  78. while(make_level())
  79. while(v=max_flow(s,INF))
  80. ans+=v;
  81. return ans;
  82. }
  83.  
  84. void dfs(int k)
  85. {
  86. f[k]=;
  87. for(int i=lin[k];i;i=e[i].nt)
  88. {
  89. if(!f[e[i].y]&&e[i].v)
  90. dfs(e[i].y);
  91. }
  92. }
  93.  
  94. int main()
  95. {
  96. freopen("a.txt","r",stdin);
  97. freopen("b.txt","w",stdout);
  98. n=read();
  99. m=read();
  100. s=,t=n;
  101. for(ll i=;i<=m;++i)
  102. {
  103. int x=read(),y=read();
  104. ll v=read();
  105. c[i].v=v;
  106. insert(x,y,v*+);
  107. }
  108. ll tmp=dinic();
  109. //cout<<tmp<<endl;
  110. printf("%lld %lld\n",tmp/,tmp%);
  111. bool flag=;
  112. for(int i=;i<=m;i++)
  113. if(c[i].v==tmp/)
  114. {
  115. cout<<i<<endl;
  116. flag=;
  117. }
  118. if(flag==) return ;
  119. dfs();
  120. //cout<<"--------"<<endl;
  121. //for(int i=1;i<=n;i++) cout<<f[i]<<' ';cout<<endl;
  122. int haha=;
  123. for(int i=;i<=n;i++)
  124. {
  125. for(int j=lin[i];j;j=e[j].nt)
  126. {
  127. if(f[i]&&!f[e[j].y]&&fe[j])
  128. cnt[++haha]=(j+)>>;
  129. }
  130. }
  131. sort(cnt+,cnt++haha);
  132. for(int i=;i<=haha;i++) cout<<cnt[i]<<endl;
  133. return ;
  134. }

  正确的代码:

  1. #include<bits/stdc++.h>
  2. #define ll long long
  3. #define INF 210000000
  4. using namespace std;
  5. struct qwq
  6. {
  7. int st,ed;
  8. ll v;
  9. int id;
  10. }ee[];
  11. int n,m;
  12. bool f[];
  13. int num[];
  14. int nnn=;
  15. struct qaq
  16. {
  17. int y,nt;
  18. ll v;
  19. }e[];
  20. int len=;
  21. int rev[];
  22. int lin[];
  23. ll ans;
  24. int level[];
  25. int q[];
  26. int s,t;
  27.  
  28. bool mycmp(qwq aa,qwq bb) {return aa.v>bb.v||(aa.v==bb.v&&aa.id<bb.id);}
  29.  
  30. void insert(int x,int y,ll v)
  31. {
  32. e[++len].v=v; e[len].y=y; e[len].nt=lin[x]; lin[x]=len; rev[len]=len+;
  33. e[++len].v=; e[len].y=x; e[len].nt=lin[y]; lin[y]=len; rev[len]=len-;
  34. }
  35.  
  36. bool make_level()
  37. {
  38. memset(level,-,sizeof(level));
  39. int head=,tail=;
  40. q[tail]=s;
  41. level[s]=;
  42. while(head++<tail)
  43. {
  44. int x=q[head];
  45. for(int i=lin[x];i;i=e[i].nt)
  46. if(e[i].v&&level[e[i].y]==-)
  47. {
  48. level[e[i].y]=level[x]+;
  49. q[++tail]=e[i].y;
  50. }
  51. }
  52. return level[t]>=;
  53. }
  54.  
  55. ll max_flow(int k,ll flow)
  56. {
  57. if(k==t) return flow;
  58. ll d=;
  59. ll maxn=;
  60. for(int i=lin[k];i&&(maxn<flow);i=e[i].nt)
  61. if(e[i].v&&level[e[i].y]==level[k]+)
  62. if(d=max_flow(e[i].y,min(e[i].v,flow-maxn)))
  63. maxn+=d,e[i].v-=d,e[rev[i]].v+=d;
  64. if(!maxn) level[k]=-;
  65. return maxn;
  66. }
  67.  
  68. ll dinic()
  69. {
  70. ll tv=;
  71. ll td=;
  72. while(make_level())
  73. while(td=max_flow(s,INF))
  74. tv+=td;
  75. return tv;
  76. }
  77.  
  78. void rebuild()
  79. {
  80. memset(e,,sizeof(e));
  81. memset(lin,,sizeof(lin));
  82. len=;
  83. for(int i=;i<=m;i++)
  84. {
  85. if(f[ee[i].id]) continue;
  86. insert(ee[i].st,ee[i].ed,ee[i].v);
  87. }
  88. }
  89.  
  90. void cut_line()
  91. {
  92. sort(ee+,ee++m,mycmp);
  93. int cnt=;
  94. memset(f,,sizeof(f));
  95. for(int i=;i<=m;i++)
  96. {
  97. f[ee[i].id]=;
  98. rebuild();
  99. int tmp=dinic();
  100. if(tmp+cnt+ee[i].v==ans)
  101. {
  102. cnt+=ee[i].v;
  103. num[++nnn]=ee[i].id;
  104. }
  105. else f[ee[i].id]=;
  106. }
  107. }
  108.  
  109. int main()
  110. {
  111. //freopen("a.txt","r",stdin);
  112. scanf("%d%d",&n,&m);
  113. s=;t=n;
  114. for(int i=;i<=m;i++)
  115. {
  116. scanf("%d%d",&ee[i].st,&ee[i].ed);
  117. scanf("%lld",&ee[i].v);
  118. ee[i].id=i;
  119. insert(ee[i].st,ee[i].ed,ee[i].v*+);
  120. }
  121. ans=dinic();
  122. printf("%lld %lld\n",ans/,ans%);
  123. ans/=;
  124. cut_line();
  125. sort(num+,num++nnn);
  126. for(int i=;i<=nnn;i++) printf("%d\n",num[i]);
  127. return ;
  128. }

  

USACO 4.4.2 追查坏牛奶 oj1341 网络流最小割问题的更多相关文章

  1. [USACO Section 4.4]追查坏牛奶Pollutant Control (最小割)

    题目链接 Solution 一眼看过去就是最小割,但是要求割边最少的最小的割. 所以要用骚操作... 建边的时候每条边权 \(w = w * (E+1) + 1;\) 那么这样建图跑出来的 \(max ...

  2. 洛谷 P1344 追查坏牛奶Pollutant Control —— 最小割

    题目:https://www.luogu.org/problemnew/show/P1344 就是求最小割: 但是还要边数最小,所以把边权都*1001+1,这样原来流量部分是*1001,最大流一样的不 ...

  3. 【题解】 bzoj3894: 文理分科 (网络流/最小割)

    bzoj3894,懒得复制题面,戳我戳我 Solution: 首先这是一个网络流,应该还比较好想,主要就是考虑建图了. 我们来分析下题面,因为一个人要么选文科要么选理科,相当于两条流里面割掉一条(怎么 ...

  4. 【bzoj3774】最优选择 网络流最小割

    题目描述 小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择了的.一个点如果被选择了,那么可以得到Bij ...

  5. 【bzoj1143】[CTSC2008]祭祀river Floyd+网络流最小割

    题目描述 在遥远的东方,有一个神秘的民族,自称Y族.他们世代居住在水面上,奉龙王为神.每逢重大庆典, Y族都会在水面上举办盛大的祭祀活动.我们可以把Y族居住地水系看成一个由岔口和河道组成的网络.每条河 ...

  6. 【bzoj1797】[Ahoi2009]Mincut 最小割 网络流最小割+Tarjan

    题目描述 给定一张图,对于每一条边询问:(1)是否存在割断该边的s-t最小割 (2)是否所有s-t最小割都割断该边 输入 第一行有4个正整数,依次为N,M,s和t.第2行到第(M+1)行每行3个正 整 ...

  7. 【bzoj1976】[BeiJing2010组队]能量魔方 Cube 网络流最小割

    题目描述 一个n*n*n的立方体,每个位置为0或1.有些位置已经确定,还有一些需要待填入.问最后可以得到的 相邻且填入的数不同的点对 的数目最大. 输入 第一行包含一个数N,表示魔方的大小. 接下来 ...

  8. 【bzoj4177】Mike的农场 网络流最小割

    题目描述 Mike有一个农场,这个农场n个牲畜围栏,现在他想在每个牲畜围栏中养一只动物,每只动物可以是牛或羊,并且每个牲畜围栏中的饲养条件都不同,其中第i个牲畜围栏中的动物长大后,每只牛可以卖a[i] ...

  9. 【bzoj3438】小M的作物 网络流最小割

    原文地址:http://www.cnblogs.com/GXZlegend/p/6801522.html 题目描述 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物 ...

随机推荐

  1. SDK支付流程

    1.普通支付流程 2.代理流程 易接.U8SDK

  2. 【志银】#define lowbit(x) ((x)&(-x))原理详解

    分析下列语句 #define lowbit(x) ((x)&(-x)) 可写成下列形式: int Lowbit(x) { return x&(-x); } 例1:x = 1 十进制转二 ...

  3. Day1 Toast/Menu/Intent传递数据

    ** --------------->未经允许,禁止转载<----------------** 今天是我读<第二行代码>的第一天,也是我第一次开始写CSDN博客,之前的笔记都在 ...

  4. linux备忘录-档案与文件系统的压缩与打包

    知识点 文件扩展名与压缩解压缩工具 .Z -> compress程序压缩的档案 .gz -> gzip程序压缩的档案 .bz2 -> bzip2程序压缩的档案 .tar -> ...

  5. Java 打印* 三角形

    package anli1; public class sanjiaoxing { public static void main(String[] agrs){ System.out.println ...

  6. 软工实践 - 第十六次作业 Alpha 冲刺 (7/10)

    队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/10013959.html 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过 ...

  7. WeUI 在小程序中使用

    才接触小程序.想找个ui框架..也不知道咋弄: 下载地址:点击打开链接 将weui-wxss-master\dist\style\weui.wxss文件导入到小程序项目的根目录下 引入weui.wxs ...

  8. finally代码块不被执行的情况总结

    以前跟别人讨论finally关键字,我总是简单的说:“fianly代码块中的代码一定会执行,一般用来清除IO资源等非内存资源(内存资源由GC机制回收)”. 今天翻书发现了几种不会执行的情况,现在总结下 ...

  9. [hdu6435]Problem J. CSGO

    题目大意:给定$n$个$A$类元素和$m$个$B$类元素,每类元素有值$S$和$k$个值$x_0,x_1,\dots,x_{k-1}(k\leqslant 5)$. 要求选出一个$A$类元素$a$和$ ...

  10. 洛谷 P3396 哈希冲突 解题报告

    P3396 哈希冲突 题目背景 此题约为NOIP提高组Day2T2难度. 题目描述 众所周知,模数的hash会产生冲突.例如,如果模的数p=7,那么4和11便冲突了. B君对hash冲突很感兴趣.他会 ...