Pollutant Control_usaco 4.4_网络流

来源:互联网 发布:网络批发平台有哪些 编辑:程序博客网 时间:2024/06/04 00:44

Description


  你第一天接手三鹿牛奶公司就发生了一件倒霉的事情:公司不小心发送了一批有三聚氰胺的牛奶。很不幸,你发现这件事的时候,有三聚氰胺的牛奶已经进入了送货网。这个送货网很大,而且关系复杂。你知道这批牛奶要发给哪个零售商,但是要把这批牛奶送到他手中有许多种途径。送货网由一些仓库和运输卡车组成,每辆卡车都在各自固定的两个仓库之间单向运输牛奶。在追查这些有三聚氰胺的牛奶的时候,有必要保证它不被送到零售商手里,所以必须使某些运输卡车停止运输,但是停止每辆卡车都会有一定的经济损失。你的任务是,在保证坏牛奶不送到零售商的前提下,制定出停止卡车运输的方案,使损失最小。
{批注:先前不知是哪个写了一个要不得的翻译,这才是正常的翻译,读起来也觉得比较健康——Cow-Tsc} {修改下,更现实——pyh119}

Input


(file milk6.in) 第一行: 两个整数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


(file milk6.out) 第1行两个整数c、t,c表示最小的损失,T表示要停止的最少卡车数。接下来t 行表示你要停止哪几条线路。如果有多种方案使损失最小,输出停止的线路最少的方案。如果仍然还有相同的方案,请选择开始输入顺序最小的。

Analysis


本来想用邻接表的但是不好打啊毕竟关系到删边什么的

首先要知道最大流=最小割(证明略)
先跑一次最大流,然后枚举删掉一条边分别跑m次最大流,如果此时最大流+删去的边的边权=原本最大流,那么可以肯定这条边在最小割集合中
在做之前要按边权降序排序,这样可以删掉最少的边

Code


/*ID:wjp13241PROG:milk6LANG:C++*/#include <stdio.h>#include <string.h>#include <stdlib.h>#include <iostream>#include <algorithm>#define fo(i,a,b) for (int i=a;i<=b;i++)#define fil(x,t) memset(x,t,sizeof(x))#define STP system("pause")#define min(x,y) x<y?x:y#define max(x,y) x>y?x:y#define INF 0x7f7f7f7f#define E 1021*2+1#define N 33using namespace std;struct edge{int x,y,w,id;}e[E];int c[N][N],bac[N][N],vis[N],p[E],cnt=0;int add(int x,int y,int w){c[x][y]+=w;bac[x][y]+=w;e[++cnt]=(edge){x,y,w,cnt};}int cmp(edge x,edge y){return x.w>y.w||x.w==y.w&&x.id<y.id;}int rec(int n){    fo(i,1,n)        fo(j,1,n)            c[i][j]=bac[i][j];}int find(int x,int n,int mn){    vis[x]=1;    if (x==n)        return mn;    fo(i,1,n)        if (c[x][i]>0&&!vis[i])        {            int d=find(i,n,min(mn,c[x][i]));            if (d!=0)            {                c[x][i]-=d;                c[i][x]+=d;                return d;            }        }    return 0;}int main(){    freopen("milk6.in","r",stdin);    freopen("milk6.out","w",stdout);    ios::sync_with_stdio(false);    int n,m;    cin>>n>>m;    fil(c,0);    fo(i,1,m)    {        int x,y,w;        cin>>x>>y>>w;        add(x,y,w);    }    rec(n);    sort(e+1,e+cnt+1,cmp);    int mxFlow=0;    fil(vis,0);    while (int tmp=find(1,n,INF))    {        fil(vis,0);        mxFlow+=tmp;    }    cout<<mxFlow<<" ";    int ans=0;    fo(i,1,cnt)    {        rec(n);        c[e[i].x][e[i].y]-=e[i].w;        int tot=0;        fil(vis,0);        while (int tmp=find(1,n,INF))        {            fil(vis,0);            tot+=tmp;        }        if (tot+e[i].w==mxFlow)        {            ans++;            p[e[i].id]=1;            mxFlow-=e[i].w;            bac[e[i].x][e[i].y]-=e[i].w;        }    }    cout<<ans<<endl;    fo(i,1,m)        if (p[i])            cout<<i<<endl;    return 0;}
0 0