• 最大流模板


    AC HDU 3061 一道最大权闭合子图裸题

    以前写的DINIC太慢了啊TAT

    老T.....

    这个DINIC加了俩优化.......

    • 当前弧优化.在一次增广中,我们总是从某个节点一条弧一条弧地放流,也就是说我们依次把弧塞满....

       把某条弧塞满以后接下来的DFS过程中就不需要再遍历这条弧了.......

       那我可以通过修改边表避免以后再遍历这些满弧........

    • 考虑广搜的时候,找到了汇点并给它标上深度,那么就可以直接跳出广搜了.

       因为在这以后标深度的节点都不能走向汇(因为它们的深度大于等于汇点深度),就是说从那些节点不会有可行流.

     

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21  
     22 using namespace std;
     23  
     24 inline int getint()
     25 {
     26     int res=0;
     27     char c=getchar();
     28     bool mi=false;
     29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     31     return mi ? -res : res;
     32 }
     33 inline ll getll()
     34 {
     35     ll res=0;
     36     char c=getchar();
     37     bool mi=false;
     38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     40     return mi ? -res : res;
     41 }
     42  
     43 db eps=1e-20;
     44 inline bool feq(db a,db b)
     45 { return fabs(a-b)<eps; }
     46 
     47 template<typename Type>
     48 inline Type avg(const Type a,const Type b)
     49 { return a+((b-a)/2); }
     50 
     51 //==============================================================================
     52 //==============================================================================
     53 //==============================================================================
     54 //==============================================================================
     55 
     56 
     57 const int INF=(1<<30)-1;
     58 
     59 struct edge
     60 {
     61     int c;
     62     int in;
     63     edge*nxt;
     64     edge*ptr;
     65 }pool[205000];
     66 edge*et;
     67 edge*eds[1050];
     68 edge*cur[1050];
     69 edge*addedge(int i,int j,int c)
     70 {
     71     et->ptr=et+1;
     72     et->in=j; et->c=c; et->nxt=eds[i]; eds[i]=et++;
     73     et->ptr=et-1;
     74     et->in=i; et->c=0; et->nxt=eds[j]; eds[j]=et++; 
     75 }
     76 
     77 int n;
     78 int st,ed;
     79 int dep[1050];
     80 int DFS(int x,int mi)
     81 {
     82     if(x==ed) return mi;
     83     int res=0,c;
     84     for(edge*&i=cur[x];i;i=i->nxt)
     85     if(i->c>0 && dep[i->in]==dep[x]+1 && ( c=DFS(i->in,min(i->c,mi)) ))
     86     {
     87         i->c-=c;
     88         i->ptr->c+=c;
     89         res+=c;
     90         mi-=c;
     91         if(!mi) break;
     92     }
     93     if(!res) dep[x]=-1;
     94     return res;
     95 }
     96 
     97 int qh,qt;
     98 int q[1050];
     99 int DINIC()
    100 {
    101     int res=0;
    102     
    103     while(true)
    104     {
    105         memset(dep,0xFF,sizeof(int)*(n+1));
    106         
    107         qh=qt=0;
    108         q[qt++]=st;
    109         dep[st]=0;
    110         bool found=false;
    111         while(qh!=qt && !found)
    112         {
    113             int x=q[qh];
    114             for(edge*i=eds[x];i && !found;i=i->nxt)
    115             if(i->c>0 && dep[i->in]==-1)
    116             {
    117                 dep[i->in]=dep[x]+1;
    118                 if(i->in==ed) { found=true; break; } 
    119                 q[qt++]=i->in;
    120             }
    121             qh++;
    122         }
    123         
    124         if(dep[ed]==-1) break;
    125         
    126         memcpy(cur,eds,sizeof(edge*)*(n+1));
    127         res+=DFS(st,INF);
    128     }
    129     
    130     return res;
    131 }
    132 
    133 
    134 int ntot,mtot;
    135 
    136 
    137 
    138 int main()
    139 {
    140     while(scanf("%d%d",&ntot,&mtot)>0)
    141     {
    142         st=ntot;
    143         ed=st+1;
    144         n=ed+1;
    145         
    146         et=pool;
    147         memset(eds,0,sizeof(edge*)*(n+1));
    148         
    149         int sum=0;
    150         
    151         for(int i=0;i<ntot;i++)
    152         {
    153             int c=getint();
    154             if(c>0) addedge(st,i,c),sum+=c;
    155             else if(c<0) addedge(i,ed,-c);
    156         }
    157         
    158         for(int i=0;i<mtot;i++)
    159         {
    160             int a,b;
    161             a=getint()-1;
    162             b=getint()-1;
    163             addedge(a,b,INF);
    164         }
    165         
    166         printf("%d\n",sum-DINIC());
    167         
    168     }
    169     
    170     return 0;
    171 }
    View Code

     

    耗时390ms,还看得过眼.......

    打一个DINIC预计时间10min左右....

     


     

     AC VIJOS P1590

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4 
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9 
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 
     16 typedef unsigned int uint;
     17 typedef long long int ll;
     18 typedef unsigned long long int ull;
     19 typedef double db;
     20 
     21 #define DBG printf("*")
     22 
     23 using namespace std;
     24 
     25 const int INF=(1<<28)-1;
     26 const ll LINF=((ll)1<<52)-1;
     27 
     28 struct edge
     29 {
     30     int in;
     31     ll c;
     32     edge*nxt;
     33     edge*ptr;
     34 }pool[100000];
     35 edge*et=pool;
     36 edge*eds[200];
     37 void addedge(int i,int j,ll c)
     38 {
     39     et->ptr=et+1;
     40     et->c=c; et->in=j; et->nxt=eds[i]; eds[i]=et++;
     41     et->ptr=et-1;
     42     et->c=0; et->in=i; et->nxt=eds[j]; eds[j]=et++; 
     43 }
     44 #define FOREACH_EDGE(i,j) for(edge*i=eds[j];i!=NULL;i=i->nxt)
     45 
     46 int n;
     47 
     48 int st,ed;
     49 int dep[200];
     50 ll DFS(int x,ll mi)
     51 {
     52     if(x==ed) return mi;
     53     ll res=0,c;
     54     FOREACH_EDGE(i,x)
     55     if(i->c>0 && dep[x]+1==dep[i->in] && (c=DFS(i->in,min(mi,i->c))) )
     56     {
     57         res+=c;
     58         i->c-=c;
     59         i->ptr->c+=c;
     60         mi-=c;
     61         if(mi<=0) break;
     62     }
     63     if(res<=0) dep[x]=-1;
     64     return res;
     65 }
     66 
     67 int qh,qt;
     68 int q[400];
     69 ll DINIC()
     70 {
     71     ll res=0;
     72     
     73     while(true)
     74     {
     75         memset(dep,0xFF,sizeof(int)*(n+1));
     76         
     77         qh=qt=0;
     78         q[qt++]=st;
     79         dep[st]=0;
     80         while(qh!=qt)
     81         {
     82             int&cur=q[qh];
     83             FOREACH_EDGE(i,cur)
     84             if(i->c>0 && dep[i->in]==-1)
     85             {
     86                 dep[i->in]=dep[cur]+1;
     87                 q[qt++]=i->in;
     88             }
     89             qh++;
     90         }
     91         
     92         if(dep[ed]==-1) break;
     93     
     94         res=max((ll)0,res);
     95         res+=DFS(st,LINF);
     96     }
     97     
     98     return res;
     99 }
    100 
    101 
    102 //blocks define
    103 #define ST(i) (i)
    104 #define ED(i) ((i)+ntot)
    105 
    106 int ntot,m;
    107 
    108 int main()
    109 {
    110     int T;
    111     scanf("%d",&T);
    112     while(T--)
    113     {
    114         scanf("%d%d",&ntot,&m);
    115         et=pool;
    116         
    117         ntot++;
    118         n=ntot*2;
    119         st=ED(0);
    120         ed=ST(ntot-1);
    121         
    122         memset(eds,0,sizeof(int)*(n+1));
    123         
    124         for(int i=1;i<ntot-1;i++)
    125         {
    126             ll c;
    127             scanf("%I64d",&c);
    128             addedge(ST(i),ED(i),c);
    129         }
    130         
    131         addedge(ST(0),ED(0),LINF);
    132         addedge(ST(ntot-1),ED(ntot-1),LINF);
    133         
    134         for(int i=0;i<m;i++)
    135         {
    136             int a,b;
    137             scanf("%d%d",&a,&b);
    138             addedge(ED(b),ST(a),LINF);
    139             addedge(ED(a),ST(b),LINF);
    140         }
    141 
    142         ll res=DINIC();
    143         
    144         if(res==0) printf("Min!\n");
    145         else if(res>=LINF) printf("Max!\n");
    146         else printf("%I64d\n",res);
    147     }
    148     
    149     return 0;
    150 }
    View Code

     



     

     


    然后是类似于DINIC的最小费用流.多路增广.存图同上,这里省略了.

     1 int n;
     2 
     3 int st,ed;
     4 int dist[205];
     5 int cost_add;
     6 bool used[205];
     7 int DFS(int x,int mi)
     8 {
     9     if(x==ed)return mi;
    10     
    11     used[x]=true;
    12     int res=0;
    13     int c;
    14     FOREACH_EDGE(i,x)
    15     if(!used[i->in] && i->c>0 && dist[i->in]==dist[x]+i->v && (c=DFS(i->in,min(i->c,mi))))
    16     {
    17         i->c-=c;
    18         i->ptr->c+=c;
    19         mi-=c;
    20         res+=c;
    21         cost_add+=c*i->v;
    22         if(mi<=0) break;
    23     }
    24     used[x]=false;
    25     if(res<=0) dist[x]=INF;
    26     return res;
    27 }
    28 
    29 int q[1000000];
    30 int qt,qh;
    31 int DINIC()
    32 {
    33     int res=0;
    34     
    35     while(true)
    36     {
    37         for(int i=0;i<n;i++)
    38         dist[i]=INF;
    39         
    40         qh=qt=0;
    41         dist[st]=0;
    42         q[qt++]=st;
    43         while(qh!=qt)
    44         {
    45             int&cur=q[qh];
    46             FOREACH_EDGE(i,cur)
    47             {
    48                 int&nxt=i->in;
    49                 if(i->c>0 && i->v + dist[cur] < dist[nxt])
    50                 {
    51                     dist[nxt]=dist[cur]+i->v;
    52                     q[qt++]=nxt;
    53                 }
    54             }
    55             qh++;
    56         }
    57         
    58         if(dist[ed]==INF) break;
    59         
    60         cost_add=0;
    61         DFS(st,INF);
    62         res+=cost_add;
    63     }
    64     
    65     return res;
    66 }
    View Code

    注意DFS中使用了used在深搜的时候避免搜到环(最短路图中可能存在0环).

     

     

    AC BZOJ 1384

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21  
     22 using namespace std;
     23  
     24 inline int getint()
     25 {
     26     int res=0;
     27     char c=getchar();
     28     bool mi=false;
     29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     31     return mi ? -res : res;
     32 }
     33 inline ll getll()
     34 {
     35     ll res=0;
     36     char c=getchar();
     37     bool mi=false;
     38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     40     return mi ? -res : res;
     41 }
     42 
     43 //==============================================================================
     44 //==============================================================================
     45 //==============================================================================
     46 //==============================================================================
     47 
     48 int INF=(1<<30)-1;
     49 
     50 struct edge
     51 {
     52     int in;
     53     int c;
     54     int v;
     55     edge*nxt;
     56     edge*ptr;
     57     bool rev;
     58 }pool[105000];
     59 int orgv[105000];
     60 edge*et=pool;
     61 edge*eds[1050];
     62 void addedge(int i,int j,int c,int v)
     63 {
     64     et->ptr=et+1; et->rev=false;
     65     et->in=j; et->c=c; et->v=v; et->nxt=eds[i]; eds[i]=et++;
     66     et->ptr=et-1; et->rev=true;
     67     et->in=i; et->c=0; et->v=-v; et->nxt=eds[j]; eds[j]=et++;
     68 }
     69 #define FOREACH_EDGE(i,j) for(edge*i=eds[j];i;i=i->nxt)
     70 
     71 int n;
     72 
     73 int cost;
     74 
     75 int dist[1050];
     76 int st,ed;
     77 bool used[1050];
     78 int DFS(int x,int mi)
     79 {
     80     if(x==ed) return mi;
     81     used[x]=true;
     82     int res=0,c;
     83     FOREACH_EDGE(i,x)
     84     if(i->c>0 && !used[i->in] && dist[x]+i->v==dist[i->in] && ( c=DFS(i->in,min(i->c,mi)) ))
     85     {
     86         i->c-=c;
     87         i->ptr->c+=c;
     88         res+=c;
     89         mi-=c;
     90         cost+=i->v*c;
     91         if(!mi) break;
     92     }
     93     if(!res) dist[x]=INF;
     94     used[x]=false;
     95     return res;
     96 }
     97 
     98 int q[4000000];
     99 int qh,qt;
    100 int DINIC()
    101 {
    102     int res=0;
    103     
    104     while(true)
    105     {
    106         for(int i=0;i<=n;i++)
    107         dist[i]=INF;
    108         
    109         qh=qt=0;
    110         q[qt++]=st;
    111         dist[st]=0;
    112         while(qh!=qt)
    113         {
    114             int x=q[qh];
    115             FOREACH_EDGE(i,x)
    116             if(i->c>0 && dist[i->in]-dist[x]>i->v)
    117             {
    118                 dist[i->in]=dist[x]+i->v;
    119                 q[qt++]=i->in;
    120             }
    121             qh++;
    122         }
    123         
    124         if(dist[ed]==INF) break;
    125         
    126         res+=DFS(st,INF);
    127     }
    128     
    129     return res;
    130 }
    131 
    132 int m,k;
    133 
    134 edge*ote;
    135 
    136 int cap[105000];
    137 int A[105000];
    138 int B[105000];
    139 int var[105000];
    140 int etot=0;
    141 
    142 int main()
    143 {
    144     n=getint()+1;
    145     m=getint();
    146     k=getint();
    147     st=1;
    148     ed=n-1;
    149     for(int i=0;i<m;i++)
    150     {
    151         int c;
    152         A[i]=getint();
    153         B[i]=getint();
    154         c=getint();
    155         orgv[i]=getint();
    156         addedge(A[i],B[i],c,1);
    157     }
    158     
    159     printf("%d ",DINIC());
    160     
    161     for(int i=1;i<n;i++)
    162     FOREACH_EDGE(e,i) e->v=0;
    163     
    164     cost=0;
    165     
    166     for(int i=0;i<m;i++)
    167     addedge(A[i],B[i],INF,orgv[i]);
    168     
    169     st=0;
    170     addedge(st,1,k,0);
    171     DINIC();
    172     printf("%d\n",cost);
    173     
    174     
    175     return 0;
    176 }
    View Code

    把这个程序放上来,主要表示在原残量网络上建图,以及最大流与最小费的相互转化的基本方法.


    AC BZOJ 1266

    最短路图转最小割

      1 #include <cstdio>
      2 #include <fstream>
      3 #include <iostream>
      4  
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <cmath>
      9  
     10 #include <queue>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <stack>
     15 #include <list>
     16  
     17 typedef unsigned int uint;
     18 typedef long long int ll;
     19 typedef unsigned long long int ull;
     20 typedef double db;
     21  
     22 using namespace std;
     23  
     24 inline int getint()
     25 {
     26     int res=0;
     27     char c=getchar();
     28     bool mi=false;
     29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     31     return mi ? -res : res;
     32 }
     33 inline ll getll()
     34 {
     35     ll res=0;
     36     char c=getchar();
     37     bool mi=false;
     38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
     39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
     40     return mi ? -res : res;
     41 }
     42 
     43 //==============================================================================
     44 //==============================================================================
     45 //==============================================================================
     46 //==============================================================================
     47 
     48 const int INF=(1<<30)-1;
     49 
     50 int n;
     51 
     52 struct ShortestPathGraph
     53 {
     54     struct edge
     55     {
     56         int in;
     57         int v;
     58         edge*nxt;
     59     }pool[205000];
     60     edge*et;
     61     edge*eds[1050];
     62     
     63     ShortestPathGraph(){ et=pool; }
     64     
     65     void addedge(int i,int j,int v)
     66     { et->in=j; et->v=v; et->nxt=eds[i]; eds[i]=et++; }
     67     
     68     void SPFA(int*dist,int st)
     69     {
     70         for(int i=0;i<n;i++) dist[i]=INF;
     71         typedef pair<int,int> pl;
     72         priority_queue<pl,vector<pl>,greater_equal<pl> > q;
     73         dist[st]=0; q.push(pl(dist[st],st));
     74         while(!q.empty())
     75         {
     76             int x=q.top().second;
     77             int d=q.top().first;
     78             q.pop();
     79             if(dist[x]<d) continue;
     80             for(edge*i=eds[x];i;i=i->nxt)
     81             if(dist[i->in]>dist[x]+i->v)
     82             {
     83                 dist[i->in]=dist[x]+i->v;
     84                 q.push(pl(dist[i->in],i->in));
     85             }
     86         }
     87     }
     88 };
     89 
     90 
     91 struct MaxflowGraph
     92 {
     93     struct edge
     94     {
     95         int in;
     96         int c;
     97         edge*nxt;
     98         edge*ptr;
     99     }pool[405000];
    100     edge*et;
    101     edge*eds[1050];
    102     edge*cur[1050];
    103     
    104     int dep[1050];
    105     
    106     int st,ed;
    107     MaxflowGraph(){ et=pool; }
    108     MaxflowGraph(int s,int t):st(s),ed(t){ et=pool; }
    109     
    110     void addedge(int i,int j,int c)
    111     {
    112         et->ptr=et+1;
    113         et->in=j; et->c=c; et->nxt=eds[i]; eds[i]=et++;
    114         et->ptr=et-1;
    115         et->in=i; et->c=0; et->nxt=eds[j]; eds[j]=et++;
    116     }
    117     
    118     int DFS(int x,int mi)
    119     {
    120         if(x==ed) return mi;
    121         int res=0,c;
    122         for(edge*&i=cur[x];i;i=i->nxt)
    123         if( i->c>0 && dep[i->in]==dep[x]+1 && ( c=DFS(i->in,min(i->c,mi)) ) )
    124         {
    125             i->c-=c;
    126             i->ptr->c+=c;
    127             res+=c;
    128             mi-=c;
    129             if(!mi) break;
    130         }
    131         if(!res) dep[x]=-1;
    132         return res;
    133     }
    134     
    135     int DINIC()
    136     {
    137         int res=0;
    138         
    139         while(true)
    140         {
    141             memset(dep,0xFF,sizeof(int)*(n+1));
    142             queue<int> q;
    143             q.push(st); dep[st]=0;
    144             while(!q.empty())
    145             {
    146                 int x=q.front(); q.pop();
    147                 for(edge*i=eds[x];i;i=i->nxt)
    148                 if(i->c>0 && dep[i->in]==-1)
    149                 {
    150                     dep[i->in]=dep[x]+1;
    151                     if(i->in==ed) break;
    152                     q.push(i->in);
    153                 }
    154             }
    155             if(dep[ed]==-1) break;
    156             memcpy(cur,eds,sizeof(edge*)*(n+1));
    157             res+=DFS(st,INF);
    158         }
    159         
    160         return res;
    161     }
    162     
    163 };
    164 
    165 
    166 int m;
    167 
    168 int A[205000];
    169 int B[205000];
    170 int D[205000];
    171 int C[205000];
    172 
    173 ShortestPathGraph G;
    174 MaxflowGraph F;
    175 
    176 int dist[10050];
    177 
    178 
    179 int main()
    180 {
    181     n=getint();
    182     m=getint();
    183     for(int i=0;i<m;i++)
    184     {
    185         A[i]=getint()-1;
    186         B[i]=getint()-1;
    187         D[i]=getint();
    188         C[i]=getint();
    189         G.addedge(A[i],B[i],D[i]);
    190         G.addedge(B[i],A[i],D[i]);
    191     }
    192     
    193     G.SPFA(dist,0);
    194     printf("%d\n",dist[n-1]);
    195     
    196     for(int i=0;i<m;i++)
    197     {
    198         if(dist[A[i]]+D[i]==dist[B[i]])
    199         F.addedge(A[i],B[i],C[i]);
    200         if(dist[B[i]]+D[i]==dist[A[i]])
    201         F.addedge(B[i],A[i],C[i]);
    202     }
    203     
    204     F.st=0;
    205     F.ed=n-1;
    206     printf("%d\n",F.DINIC());
    207     
    208     
    209     return 0;
    210 }
    View Code

    昨天WA了7次,今天重写一遍就A了.....

    还是不知道原来错在哪....可能是双向边的处理.....

    注意原图无向,但最短路图是有向的,对于原图每条边(x,y),重构图时(x,y)与(y,x)都要判断,并且分开连边.

    写多图(图转图)的题千万不要总想着去节约代码量! 清晰的结构带来的效率远比节约四分之一代码量要高......

  • 相关阅读:
    C#数据结构一:基础知识
    使用工厂方法模式实现多数据库WinForm手机号码查询器(附源码)
    我的个人年度总结
    CutePsWheel javascript libary:控制输入文本框为可使用滚轮控制的js库
    CSS制作无图片圆角矩形
    将SqlServer数据库转换Sqlite的工具
    原创电子书:C#难点逐个击破
    (译)在非IE浏览器中实现“灰阶化”
    extjs 记录一下
    Ext.Window相关
  • 原文地址:https://www.cnblogs.com/DragoonKiller/p/4295953.html
Copyright © 2020-2023  润新知