TZOJ 5110 Pollutant Control(边数最少最小割最小字典序输出)

时间:2019-10-30
本文章向大家介绍TZOJ 5110 Pollutant Control(边数最少最小割最小字典序输出),主要包括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