zoukankan      html  css  js  c++  java
  • USACO 4.4.2 追查坏牛奶 oj1341 网络流最小割问题

    描述 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[100];
      6 int q[100];
      7 int lin[100];
      8 int rev[5500];
      9 bool f[100]; 
     10 bool fe[5500];
     11 int len=0;
     12 ll ans=0;
     13 int cnt[5500];
     14 struct www
     15 {
     16     ll v;
     17     int id;    
     18 }a[40][40],b[40][40],c[1011];
     19 ll n,m;
     20 ll s,t;
     21 struct qaq{
     22     int nt,y;
     23     ll v;
     24 }e[5500];
     25 
     26 char buf[1<<15],*fs,*ft;
     27 inline char getc(){ return(fs==ft && (ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++; }
     28 ll read()
     29 {
     30     ll x=0;
     31     char ch=getc();
     32     while(!isdigit(ch)) ch=getc();
     33     while(isdigit(ch)) {x=(x<<3)+(x<<1)+ch-'0'; 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+1; fe[len]=1;
     40     e[++len].nt=lin[y]; e[len].v=0; e[len].y=x; lin[y]=len; rev[len]=len-1;
     41 }
     42 
     43 bool make_level()
     44 {
     45     ll head=0,tail=1;
     46     memset(level,-1,sizeof(level));
     47     q[1]=s;level[s]=0;
     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]==-1)
     53             {
     54                 level[e[i].y]=level[x]+1;
     55                 q[++tail]=e[i].y;
     56             }
     57     }
     58     return level[t]>=0;
     59 }
     60 
     61 ll max_flow(ll k,ll flow)
     62 {
     63     if(k==t) return flow;
     64     ll maxflow=0;
     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]+1)
     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]=-1;
     71     return maxflow;
     72 }
     73 
     74 ll dinic()
     75 {
     76     ans=0;
     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]=1;
     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=1,t=n;
    101     for(ll i=1;i<=m;++i)
    102     {
    103         int x=read(),y=read();
    104         ll v=read();
    105         c[i].v=v;
    106         insert(x,y,v*1001+1);
    107     }
    108     ll tmp=dinic();
    109     //cout<<tmp<<endl;
    110     printf("%lld %lld
    ",tmp/1001,tmp%1001);
    111     bool flag=0;
    112     for(int i=1;i<=m;i++)
    113         if(c[i].v==tmp/1001)
    114         {
    115             cout<<i<<endl;
    116             flag=1;
    117         }
    118     if(flag==1) return 0;
    119     dfs(1);
    120     //cout<<"--------"<<endl;
    121     //for(int i=1;i<=n;i++) cout<<f[i]<<' ';cout<<endl;
    122     int haha=0;
    123     for(int i=1;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+1)>>1;
    129         }
    130     }
    131     sort(cnt+1,cnt+1+haha);
    132     for(int i=1;i<=haha;i++) cout<<cnt[i]<<endl;
    133     return 0;
    134 }
    View Code

      正确的代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define INF 210000000
    using namespace std;
    struct qwq
    {
        int st,ed;
        ll v;
        int id;
    }ee[1010];
    int n,m;
    bool f[1010];
    int num[1010];
    int nnn=0;
    struct qaq
    {
        int y,nt;
        ll v;
    }e[3000];
    int len=0;
    int rev[3000];
    int lin[50];
    ll ans;
    int level[50];
    int q[50];
    int s,t;
    
    bool mycmp(qwq aa,qwq bb) {return aa.v>bb.v||(aa.v==bb.v&&aa.id<bb.id);}
    
    void insert(int x,int y,ll v)
    {
        e[++len].v=v; e[len].y=y; e[len].nt=lin[x]; lin[x]=len; rev[len]=len+1;
        e[++len].v=0; e[len].y=x; e[len].nt=lin[y]; lin[y]=len; rev[len]=len-1;
    }
    
    bool make_level()
    {
        memset(level,-1,sizeof(level));
        int head=0,tail=1;
        q[tail]=s;
        level[s]=0;
        while(head++<tail)
        {
            int x=q[head];
            for(int i=lin[x];i;i=e[i].nt)
                if(e[i].v&&level[e[i].y]==-1)
                {
                    level[e[i].y]=level[x]+1;
                    q[++tail]=e[i].y;
                }
        }
        return level[t]>=0;
    }
    
    ll max_flow(int k,ll flow)
    {
        if(k==t) return flow;
        ll d=0;
        ll maxn=0;
        for(int i=lin[k];i&&(maxn<flow);i=e[i].nt)
            if(e[i].v&&level[e[i].y]==level[k]+1)
                if(d=max_flow(e[i].y,min(e[i].v,flow-maxn)))
                    maxn+=d,e[i].v-=d,e[rev[i]].v+=d;
        if(!maxn) level[k]=-1;
        return maxn;
    }
    
    ll dinic()
    {
        ll tv=0;
        ll td=0;
        while(make_level())
            while(td=max_flow(s,INF))
                tv+=td;
        return tv;
    }
    
    void rebuild()
    {
        memset(e,0,sizeof(e));
        memset(lin,0,sizeof(lin));
        len=0;
        for(int i=1;i<=m;i++)
        {
            if(f[ee[i].id]) continue;
            insert(ee[i].st,ee[i].ed,ee[i].v);
        }
    }
    
    void cut_line()
    {
        sort(ee+1,ee+1+m,mycmp);
        int cnt=0;
        memset(f,0,sizeof(f));
        for(int i=1;i<=m;i++)
        {
            f[ee[i].id]=1;
            rebuild();
            int tmp=dinic();
            if(tmp+cnt+ee[i].v==ans)
            {
                cnt+=ee[i].v;
                num[++nnn]=ee[i].id;
            }
            else f[ee[i].id]=0;
        }
    }
    
    int main()
    {
        //freopen("a.txt","r",stdin);
        scanf("%d%d",&n,&m);
        s=1;t=n;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&ee[i].st,&ee[i].ed);
            scanf("%lld",&ee[i].v);
            ee[i].id=i;
            insert(ee[i].st,ee[i].ed,ee[i].v*1001+1);
        }
        ans=dinic();
        printf("%lld %lld
    ",ans/1001,ans%1001);
        ans/=1001;
        cut_line();
        sort(num+1,num+1+nnn);
        for(int i=1;i<=nnn;i++) printf("%d
    ",num[i]);
        return 0;
    }
    View Code

      

  • 相关阅读:
    Windows提权列表
    Metasploit之多种后门生成
    Metasploit下添加新exploit
    Linux常用命令
    Drozer快速使用指南
    数值
    null, undefined 和布尔值
    数据类型概述
    JavaScript 的基本语法
    JavaScript 语言的历史
  • 原文地址:https://www.cnblogs.com/snifemoree/p/6901239.html
Copyright © 2011-2022 走看看