网络流网络流小总结

Posted Konjak谷弱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络流网络流小总结相关的知识,希望对你有一定的参考价值。

一、dinic最大流

我的模板。模板上已经有了dfs上的优化(比我以前的快多了。。)优化啊优化。

bool bfs(int st,int ed)
{
    while(!q.empty()) q.pop();
    memset(d,-1,sizeof(d));
    q.push(st);
    d[st]=0;
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(int i=first[x];i!=-1;i=a[i].next)
        {
            int y=a[i].y;
            if(d[y]==-1 && a[i].d>0)
            {
                d[y]=d[x]+1;
                q.push(y);
            }
        }    
    }
    return (d[ed]!=-1);
}

int dfs(int x,int flow,int ed)
{
    int k,p,r=0;
    if(x==ed) return flow;
    for(int i=first[x];i!=-1;i=a[i].next)
    {
        int y=a[i].y;
        if(d[y]==d[x]+1 && a[i].d>0)
        {
            p=minn(a[i].d,flow-r);
            p=dfs(y,p,ed);
            r+=p; //优化,把从这个点开始能流的全部流了
            a[i].d-=p;
            a[i^1].d+=p;
        }
                if(r==flow) break; // 优化
    }
    if(!r) d[x]=-1;  //优化
    return r;
}

int dinic(int st,int ed)
{
    int ans=0;
    while(bfs(st,ed))
    {
        int k;
        while(k=dfs(st,INF,ed)) ans+=k;
    }
    return ans;
}
dinic

 

 

二、上下界网络流

建立超级源点ss,超级汇点tt(上图中的s改为ss,t改为tt)

对于每条x到y,下界为k1,上界为k2的边(x,y,k1,k2),拆成如图这种形式:(x,y,k2-k1)(自由流),(ss,y,k1)(必须流入),(x,tt,k1)(必须流出)。

(1)没有源点和汇点:

可行流:跑一遍最大流,看是否满流。满流则有可行流。

最大流:每条边加一个费用f=1,然后跑最大费用循环流(详见下面)。

最小流:每条边加一个费用f=1,然后跑最小费用循环流。

(2)有源点和汇点:

原来的源点s,原来的汇点t。在s和t之间建边(t,s,INF),使原图变为无源汇的循环流。

可行流:拆边后跑一遍最大流,满流则有可行流。

最大流:去掉ss、tt(去掉后无论怎么跑都是已经满足了下界的可行流),然后从原来的源汇点s到t跑一遍最大流,让残余网络的增广路全部加上去。此时(s,t,INF)的那条边的反向边(t,s)的流量就是答案。

最小路:去掉ss、tt后,从原来的源汇点t到s跑一遍最大流(逆向求解,让最多的流量还回去)。

上下界网络路讲解:http://www.cnblogs.com/kane0526/archive/2013/04/05/3001108.html

模板(poj2396)

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<queue>
  6 #include<vector>
  7 using namespace std;
  8 
  9 const int N=500,M=500,INF=(int)1e9;
 10 const int S=N+M+4;
 11 int n,m,s,t,ss,tt,len,sum,bk;
 12 int d[N+M+4],p[N][M],first[N+M+4],map[2][N][M];
 13 struct node{int x,y,d,next;}a[N*M*2];
 14 queue<int> q;
 15 
 16 int minn(int x,int y){return x<y ? x:y;}
 17 int maxx(int x,int y){return x>y ? x:y;}
 18 
 19 void ins(int x,int y,int d)
 20 {
 21     a[++len].x=x;a[len].y=y;a[len].d=d;
 22     a[len].next=first[x];first[x]=len;
 23     if(x==ss) sum+=d;
 24     swap(x,y);
 25     a[++len].x=x;a[len].y=y;a[len].d=0;
 26     a[len].next=first[x];first[x]=len;
 27 }
 28 
 29 void make_edge(int x,int y)
 30 {
 31     if(map[0][x][y]>map[1][x][y]) bk=0;
 32     if(map[0][x][y]==0) ins(x,y,map[1][x][y]);
 33     else
 34     {
 35         ins(ss,y,map[0][x][y]);
 36         ins(x,tt,map[0][x][y]);
 37         ins(x,y,map[1][x][y]-map[0][x][y]);
 38     }
 39 }
 40 
 41 void build(char c,int x,int y,int z)
 42 {
 43     int t1=0,t2=INF;
 44     if(c==\'=\') t1=t2=z;
 45     if(c==\'>\') t1=z+1;
 46     if(c==\'<\') t2=z-1;
 47     map[0][x][y]=maxx(map[0][x][y],t1);
 48     map[1][x][y]=minn(map[1][x][y],t2);
 49     
 50 }
 51 
 52 bool bfs(int st,int ed)
 53 {
 54     while(!q.empty()) q.pop();
 55     memset(d,-1,sizeof(d));
 56     q.push(st);
 57     d[st]=0;
 58     while(!q.empty())
 59     {
 60         int x=q.front();q.pop();
 61         for(int i=first[x];i!=-1;i=a[i].next)
 62         {
 63             int y=a[i].y;
 64             if(d[y]==-1 && a[i].d>0)
 65             {
 66                 d[y]=d[x]+1;
 67                 q.push(y);
 68             }
 69         }    
 70     }
 71     return (d[ed]!=-1);
 72 }
 73 
 74 int dfs(int x,int flow,int ed)
 75 {
 76     int k,p,r=0;
 77     if(x==ed) return flow;
 78     for(int i=first[x];i!=-1;i=a[i].next)
 79     {
 80         int y=a[i].y;
 81         if(d[y]==d[x]+1 && a[i].d>0)
 82         {
 83             p=minn(a[i].d,flow-r);
 84             p=dfs(y,p,ed);
 85             r+=p;
 86             a[i].d-=p;
 87             a[i^1].d+=p;
 88         }
 89     }
 90     if(!r) d[x]=-1;
 91     return r;
 92 }
 93 
 94 int dinic(int st,int ed)
 95 {
 96     int ans=0;
 97     while(bfs(st,ed))
 98     {
 99         int k;
100         while(k=dfs(st,INF,ed)) ans+=k;
101     }
102     return ans;
103 }
104 
105 int main()
106 {
107     freopen("a.in","r",stdin);
108     freopen("a.out","w",stdout);
109     int T;
110     scanf("%d",&T);
111     while(T--)
112     {
113         scanf("%d%d",&n,&m);
114         int x,y,z,k;
115         char c;
116         s=n+m+1;t=s+1;ss=t+1;tt=ss+1;
117         len=-1;sum=0;bk=1;
118         memset(first,-1,sizeof(first));
119         memset(map[0],0,sizeof(map[0]));
120         memset(map[1],63,sizeof(map[1]));
121         memset(p,0,sizeof(p));
122         int sum1=0,sum2=0;
123         for(int i=1;i<=n;i++)
124         {
125             scanf("%d",&x);
126             map[0][s][i]=map[1][s][i]=x;
127             make_edge(s,i);
128             sum1+=x;
129         }
130         for(int i=n+1;i<=n+m;i++)
131         {
132             scanf("%d",&x);
133             map[0][i][t]=map[1][i][t]=x;
134             make_edge(i,t);
135             sum2+=x;
136         }
137         if(sum1!=sum2) bk=0;
138         scanf("%d",&k);
139         for(int i=1;i<=k;i++)
140         {
141             scanf("%d%d",&x,&y);getchar();
142             scanf("%c%d",&c,&z);
143             if(x && y) build(c,x,y+n,z);
144             if(!x && y)
145                 for(int j=1;j<=n;j++)
146                     build(c,j,y+n,z);
147             if(x && !y)
148                 for(int j=1;j<=m;j++)
149                     build(c,x,j+n,z);
150             if(!x && !y)
151                 for(int j=1;j<=n;j++)
152                     for(int l=1;l<=m;l++)
153                         build(c,j,l+n,z);
154         }
155         for(int i=1;i<=n;i++)
156             for(int j=n+1;j<=n+m;j++)
157                 make_edge(i,j);
158         ins(t,s,INF);
159         if(!bk || dinic(ss,tt)!=sum) printf("IMPOSSIBLE\\n");
160         else 
161         {
162             for(int i=0;i<len;i++)
163             {
164                 x=a[i].x;y=a[i].y;
165                 if(x<=n+m && y<=n+m)
166                 {
167                     if(!p[x][y-n]) p[x][y-n]=map[0][x][y]+a[i^1].d;
168                 }
169             }
170             for(int i=1;i<=n;i++)
171             {
172                 for(int j=1;j<=m;j++)                    
173                     printf("%d ",p[i][j]);
174                 printf("\\n");
175             }
176         }
177         printf("\\n");
178     }
179     return 0;
180 }
poj2396

 

三、最小费用最大流

在满足最大流的前提下求最小费用,就是在bfs的时候找一条费用最小的增广路。

 1 void ins(int x,int y,int d,int f)
 2 {
 3     a[++len].x=x;a[len].y=y;a[len].d=d;a[len].f=f;
 4     a[len].next=first[x];first[x]=len;
 5     a[++len].x=y;a[len].y=x;a[len].d=0;a[len].f=-f;
 6     a[len].next=first[y];first[y]=len;
 7 }
 8 
 9 int bfs(int st,int ed)
10 {
11     while(!q.empty()) q.pop();
12     memset(pre,-1,sizeof(pre));
13     memset(dis,63,sizeof(dis));
14     memset(in,0,sizeof(in));
15     memset(flow,0,sizeof(flow));
16     pre[st]=0;dis[st]=0;in[st]=1;flow[st]=INF;q.push(st);
17     while(!q.empty())
18     {
19         int x=q.front();in[x]=0;q.pop();
20         for(int i=first[x];i!=-1;i=a[i].next)
21         {
22             int y=a[i].y;
23             if(a[i].d && dis[y]>dis[x]+a[i].f)
24             {
25                 dis[y]=dis[x]+a[i].f;
26                 pre[y]=i;
27                 flow[y]=minn(a[i].d,flow[x]);
28                 if(!in[y]) {in[y]=1;q.push(y);}
29             }
30         }
31     }
32     if(pre[ed]==-1) return -1;
33     return flow[ed];
34 }
35 
36 void MFMC(int st,int ed)//max flow min cost
37 {
38     int k,p;
39     fl=0,cl=0;
40     while((k=bfs(st,ed))!=-1)
41     {
42         fl+=k;
43         cl+=dis[ed]*k;
44         p=ed;
45         while(p!=st)
46         {
47             a[pre[p]].d-=k;
48             a[pre[p]^1].d+=k;
49             p=a[pre[p]].x;
50         }
51     }
52 }
费用流

 

四、最小割

根据最大流最小割原理,最大流就是最小割。主要是建图模型。

经典例题:一些资源,要不给A,要不给B,有相应的收益,问最大收益。写在我的题表里了。

我写了题解:http://www.cnblogs.com/KonjakJuruo/p/5516479.html

 

五、最大费用循环流

每条边有上下界k1、k2,费用f。问最大费用循环流。

对于每条边(x,y,k1,k2,f),拆成:

1.(x,y,k1,k1,f)  (再按上下界拆边,即(s,y,k1,f) (x,t,k1,f)), (x到y之间一定要流k1的流量)

2.(y,x,k2-k1,-f)  ,   (s,y,k2-k1,0)   ,   (x,t,k2-f1,f);  (x到y之间有k2-k1的自由流,先假设全部都可以得到,然后建(y,x,k2-k1,-f)就是给它反悔的机会,如果必须反悔就减回f*流量)

跑最大流,用k2的和判满流,满流则有解。

 

重点来了,题表及代码:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<queue>
  6 #include<vector>
  7 using namespace std;
  8 
  9 const int N=500,M=500,INF=(int)1e9;
 10 const int S=N+M+4;
 11 int n,m,s,t,ss,tt,len,sum,bk;
 12 int d[N+M+4],p[N][M],first[N+M+4],map[2][N][M];
 13 struct node{int x,y,d,next;}a[N*M*2];
 14 queue<int> q;
 15 
 16 int minn(int x,int y){return x<y ? x:y;}
 17 int maxx(int x,int y){return x>y ? x:y;}
 18 
 19 void ins(int x,int y,int d)
 20 {
 21     a[++len].x=x;a[len].y=y;a[len].d=d;
 22     a[len].next=first[x];first[x]=len;
 23     if(x==ss) sum+=d;
 24     swap(x,y);
 25     a[++len].x=x;a[len].y=y;a[len].d=0;
 26     a[len].next=first[x];first[x]=len;
 27 }
 28 
 29 void make_edge(int x,int y)
 30 {
 31     if(map[0][x][y]>map[1][x][y]) bk=0;
 32     if(map[0][x][y]==0) ins(x,y,map[1][x][y]);
 33     else
 34     {
 35         ins(ss,y,map[0][x][y]);
 36         ins(x,tt,map[0][x][y]);
 37         ins(x,y,map[1][x][y]-map[0][x][y]);
 38     }
 39 }
 40 
 41 void build(char c,int x,int y,int z)
 42 {
 43     int t1=0,t2=INF;
 44     if(c==\'=\') t1=t2=z;
 45     if(c==\'>\') t1=z+1;
 46     if(c==\'<\') t2=z-1;
 47     map[0][x][y]=maxx(map[0][x][y],t1);
 48     map[1][x][y]=minn(map[1][x][y],t2);
 49     
 50 }
 51 
 52 bool bfs(int st,int ed)
 53 {
 54     while(!q.empty()) q.pop();
 55     memset(d,-1,sizeof(d));
 56     q.push(st);
 57     d[st]=0;
 58     while(!q.empty())
 59     {
 60         int x=q.front();q.pop();
 61         for(int i=first[x];i!=-1;i=a[i].next)
 62         {
 63             int y=a[i].y;
 64             if(d[y]==-1 && a[i].d>0)
 65             {
 66                 d[y]=d[x]+1;
 67                 q.push(y);
 68             }
 69         }    
 70     }
 71     return (d[ed]!=-1);
 72 }
 73 
 74 int dfs(int x,int flow,int ed)
 75 {
 76     int k,p,r=0;
 77     if(x==ed) return flow;
 78     for(int i=first[x];i!=-C#流总结(文件流内存流网络流BufferedStreamStreamReader/StreamWriterTextReader/TextWriter)

费用流网络流24题P4014 分配问题.md

待更新算法

学习笔记:网络流

网络流

网络流