zoukankan      html  css  js  c++  java
  • hdu 3549 Flow Problem(最大流入门)

    Problem Description

    Network flow is a well-known difficult problem for ACMers. Given a graph, your task is to find out the maximum flow for the weighted directed graph.

    Input

    The first line of input contains an integer T, denoting the number of test cases.
    For each test case, the first line contains two integers N and M, denoting the number of vertexes and edges in the graph. (2 <= N <= 15, 0 <= M <= 1000)
    Next M lines, each line contains three integers X, Y and C, there is an edge from X to Y and the capacity of it is C. (1 <= X, Y <= N, 1 <= C <= 1000)

    Output

    For each test cases, you should output the maximum flow from source 1 to sink N.

    Sample Input

    2
    3 2
    1 2 1
    2 3 1
    3 3
    1 2 1
    2 3 1
    1 3 1

    Sample Output

    Case 1: 1
    Case 2: 2
    解题思路:Dicic实现,即每个阶段先进行1次bfs给图分层,然后在该图上进行1次或多次寻找增广路,如果当前层次图中已找不到增广路,就重新给图分层,然后继续找增广路,只要t的level小于0就说明当前网络已达到最大流。时间复杂度大概为O(|E||V|2)。
    AC代码一(312ms):
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int INF=0x3f3f3f3f;
     4 const int maxn=1005;//int cnt=1;
     5 struct edge{ int to, cap; size_t rev;
     6     edge(int _to, int _cap, size_t _rev) :to(_to), cap(_cap), rev(_rev){}//构造函数,初始化结构体变量
     7 };//指向节点to,边容量是cap,rev是记录为当前邻接点to反向边的编号
     8 vector<edge> G[maxn];//邻接表,G[i][j]表示节点i连接的第j条边包含的所有信息
     9 int t,n,m,x,y,c,level[maxn];//level数组在bfs时为分层图所用
    10 void add_edge(int from,int to,int cap){//向图中增加一条从s到t容量为cap的边
    11     G[from].push_back(edge( to, cap, G[to].size() ));
    12     G[to].push_back(edge( from, 0, G[from].size() - 1));//关键:反向建边,初始流量为0
    13 }
    14 //bfs给图分层次
    15 void bfs(int s){
    16     memset(level,-1,sizeof(level));//刚开始每个节点的层次置为-1
    17     queue<int> que;//队列实现bfs
    18     level[s]=0;//源点s为第0层
    19     que.push(s);
    20     while(!que.empty()){//给图分层
    21         int v=que.front();que.pop();
    22         for(size_t i=0;i<G[v].size();++i){//遍历节点v与之相连的每条边
    23             edge &e=G[v][i];//取出与节点v相连的第i条边
    24             if(e.cap>0&&level[e.to]<0){//如果边残余流量大于0,且节点e.to还未分层
    25                 level[e.to]=level[v]+1;//节点e.to的层次为指向它的节点v所在层次数加1
    26                 que.push(e.to);
    27             }
    28         }
    29     }
    30 }
    31 //dfs寻找增广路,寻找当前图中s-->t的一条增广路
    32 int dfs(int v,int t,int f){//v->t(t为汇点),当前增广路径上的最小剩余流量为f
    33     if(v==t)return f;//到达汇点t
    34     for(size_t i=0;i<G[v].size();++i){//遍历节点v与之相连的每条边
    35         edge &e=G[v][i];//取出与节点v相连的第i条边
    36         if(e.cap>0 && level[v]<level[e.to]){//如果该边残流量大于0,且邻接点e.to是v的下一级,就增广下去
    37             //cout<<"当前遍历到的点v:"<<v<<",邻接点to:"<<e.to<<endl;
    38             int d=dfs(e.to,t,min(f,e.cap));//维护当前增广路上最小的剩余流量f
    39             if(d>0){//若f>0,说明找到了一条增广路
    40                 //cout<<v<<"-->"<<e.to<<",边容量为:"<<e.cap<<endl;
    41                 e.cap-=d;//正向边流量减去f
    42                 G[e.to][e.rev].cap+=d;//反向边流量加上f
    43                 return d;//沿着增广路回溯到源点s,不会在途中去深搜其他点,返回当前增广路上的最小剩余流量
    44             }
    45         }
    46     }
    47     return 0;//否则说明没有增广路,返回0
    48 }
    49 //Dinic算法实现最大流,每个阶段执行完一次bfs分层之后,只需查找当前层次图中是否还增广路即可
    50 int max_flow(int s,int t){
    51     int flow=0;
    52     while(1){
    53         bfs(s);//每个阶段先bfs将图分层标记
    54         if(level[t]<0)return flow;
    55         //如果分层之后,汇点t的层次小于0,即未被分层,说明再无增广路,则直接返回当前最大流量
    56         int f=dfs(s,t,INF);
    57         //cout<<"第"<<cnt++<<"次的最小剩余容量为:"<<f<<endl;
    58         while(f>0){//在该层次图中找到增广路
    59             flow+=f;//累加到最大流中
    60             f=dfs(s,t,INF);//继续找该层次图中是否还有增广路,直到f为0,
    61             //cout<<"第"<<cnt++<<"次的最小剩余容量为:"<<f<<endl;
    62         }
    63     }
    64 }
    65 int main(){
    66     while(~scanf("%d",&t)){
    67         for(int cas=1;cas<=t;++cas){
    68             scanf("%d%d",&n,&m);//cnt=1;
    69             for(int i=0;i<=n;++i)G[i].clear();
    70             while(m--){
    71                 scanf("%d%d%d",&x,&y,&c);
    72                 add_edge(x,y,c);
    73             }
    74             printf("Case %d: %d
    ",cas,max_flow(1,n));
    75         }
    76     }
    77     return 0;
    78 }

    AC代码二(93ms):当前弧优化Dinic算法。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int INF=0x3f3f3f3f;
     4 const int maxn=1005;
     5 struct edge{ int to,cap;size_t rev;
     6     edge(int _to, int _cap, size_t _rev):to(_to),cap(_cap),rev(_rev){}
     7 };
     8 int T,n,m,x,y,c,level[maxn];queue<int> que;vector<edge> G[maxn];size_t curfir[maxn];
     9 void add_edge(int from,int to,int cap){
    10     G[from].push_back(edge(to,cap,G[to].size()));
    11     G[to].push_back(edge(from,0,G[from].size()-1));
    12 }
    13 bool bfs(int s,int t){
    14     memset(level,-1,sizeof(level));
    15     while(!que.empty())que.pop();
    16     level[s]=0;
    17     que.push(s);
    18     while(!que.empty()){
    19         int v=que.front();que.pop();
    20         for(size_t i=0;i<G[v].size();++i){
    21             edge &e=G[v][i];
    22             if(e.cap>0&&level[e.to]<0){
    23                 level[e.to]=level[v]+1;
    24                 que.push(e.to);
    25             }
    26         }
    27     }
    28     return level[t]<0?false:true;
    29 }
    30 int dfs(int v,int t,int f){
    31     if(v==t)return f;
    32     for(size_t &i=curfir[v];i<G[v].size();++i){
    33         edge &e=G[v][i];
    34         if(e.cap>0&&(level[v]+1==level[e.to])){
    35             int d=dfs(e.to,t,min(f,e.cap));
    36             if(d>0){
    37                 e.cap-=d;
    38                 G[e.to][e.rev].cap+=d;
    39                 return d;
    40             }
    41         }
    42     }
    43     return 0;
    44 }
    45 int max_flow(int s,int t){
    46     int f,flow=0;
    47     while(bfs(s,t)){
    48         memset(curfir,0,sizeof(curfir));
    49         while((f=dfs(s,t,INF))>0)flow+=f;
    50     }
    51     return flow;
    52 }
    53 int main(){
    54     while(~scanf("%d",&T)){
    55         for(int cas=1;cas<=T;++cas){
    56             scanf("%d%d",&n,&m);
    57             for(int i=0;i<=n;++i)G[i].clear();
    58             while(m--){
    59                 scanf("%d%d%d",&x,&y,&c);
    60                 add_edge(x,y,c);
    61             }
    62             printf("Case %d: %d
    ",cas,max_flow(1,n));
    63         }
    64     }
    65     return 0;
    66 }
  • 相关阅读:
    64.Find the Duplicate Number(发现重复数字)
    63.Perfect Squares(完美平方数)
    62.Longest Valid Parentheses(最长的有效括号)
    61.Merge k Sorted Lists(合并k个排序链表)
    60.Median of Two Sorted Arrays(两个排序数组的中位数)
    59.Target Sum(目标和)
    58.Partition Equal Subset Sum(判断一个数组是否可以分成和相等的两个数组)
    57.Queue Reconstruction by Height(按身高重建对列)
    56.Decode String(解码字符串)
    55.Top K Frequent Elements(出现次数最多的k个元素)
  • 原文地址:https://www.cnblogs.com/acgoto/p/9845914.html
Copyright © 2011-2022 走看看