• HDU3549 最大流 裸题


    EK算法 时间复杂度o(n*m*m)  因为有反向边每次bfs时间为 n*m 每次删一条边 最多m次

     代码

     1 #include<iostream>
     2 #include<string.h>
     3 #include<vector>
     4 #include<stdio.h>
     5 #include<queue>
     6 using namespace std;
     7 const int maxn=2e5+10,inf=0x3f3f3f3f;
     8 typedef long long ll;
     9 struct edge
    10 {
    11     int from,to,c,f;
    12     edge(int u,int v,int c,int f):from(u),to(v),c(c),f(f) {}
    13 };
    14 int n,m;
    15 vector<edge> edges;
    16 vector<int> g[maxn];
    17 int a[maxn],p[maxn];
    18 void init()
    19 {
    20     for(int i=0; i<=n; i++) g[i].clear();
    21     edges.clear();
    22 }
    23 void addedge(int from,int to,int c)
    24 {
    25     edges.push_back(edge(from,to,c,0));
    26     edges.push_back(edge(to,from,0,0));
    27     int siz=edges.size();
    28     g[from].push_back(siz-2);
    29     g[to].push_back(siz-1);
    30 }
    31 ll maxflow(int s,int t)
    32 {
    33     ll flow=0;
    34     while(1)
    35     {
    36         memset(a,0,sizeof(a));
    37         queue<int> q;
    38         q.push(s);
    39         a[s]=inf;
    40         while(!q.empty())
    41         {
    42             int x=q.front();
    43             q.pop();
    44             //  cout<<x<<" "<<g[x].size()<<endl;
    45             for(int i=0; i<g[x].size(); i++)
    46             {
    47                 int u=g[x][i];
    48                 edge &e=edges[u];
    49                 //cout<<e.from<<" "<<e.to<<endl;
    50                 if(!a[e.to]&&e.c>e.f)
    51                 {
    52                     p[e.to]=u; //存边
    53                     a[e.to]=min(a[x],e.c-e.f);
    54                     q.push(e.to);
    55                 }
    56             }
    57             if(a[t])break;
    58         }
    59         // cout<<a[t]<<endl;                   //a[t]为一次增广值
    60         if(!a[t]) break;
    61         for(int u=t; u!=s; u=edges[p[u]].from)//流量修改
    62         {
    63             edges[p[u]].f+=a[t];
    64             edges[p[u]^1].f-=a[t];
    65         }
    66         flow+=(ll)a[t];
    67     }
    68     return flow;
    69 }
    70 int main()
    71 {
    72     int t,u,v,c,f,kase=1;
    73     cin>>t;
    74     while(t--)
    75     {
    76         cin>>n>>m;
    77         init();
    78         for(int i=0; i<m; i++)
    79         {
    80             cin>>u>>v>>c;
    81             addedge(u-1,v-1,c);
    82         }
    83         printf("Case %d: %d
    ",kase++,maxflow(0,n-1));
    84         //cout<<maxflow(0,n-1)<<endl;
    85     }
    86 }

    Dinic  时间复杂度o(n*n*m)最多计算n-1次阻塞流 每次n*m  很松的上界

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e3+20,mod=1e9+7,inf=0x3f3f3f3f;
     4 typedef long long ll;
     5 struct edge
     6 {
     7     int from,to,c,f;
     8     edge(int u,int v,int c,int f):from(u),to(v),c(c),f(f) {}
     9 };
    10 int n,m;
    11 vector<edge> edges;
    12 vector<int> g[maxn];
    13 int d[maxn];//从起点到i的距离
    14 int cur[maxn];//当前弧下标
    15 void init()
    16 {
    17     for(int i=0; i<=n; i++) g[i].clear();
    18     edges.clear();
    19 }
    20 void addedge(int from,int to,int c) //加边 支持重边
    21 {
    22     edges.push_back(edge(from,to,c,0));
    23     edges.push_back(edge(to,from,0,0));
    24     int siz=edges.size();
    25     g[from].push_back(siz-2);
    26     g[to].push_back(siz-1);
    27 }
    28 int bfs(int s,int t) //构造一次层次图
    29 {
    30     memset(d,-1,sizeof(d));
    31     queue<int> q;
    32     q.push(s);
    33     d[s]=0;
    34     while(!q.empty())
    35     {
    36         int x=q.front();q.pop();
    37         for(int i=0;i<g[x].size();i++)
    38         {
    39             edge &e=edges[g[x][i]];
    40             if(d[e.to]<0&&e.f<e.c) //d[e.to]=-1表示没访问过
    41             {
    42                 d[e.to]=d[x]+1;
    43                 q.push(e.to);
    44             }
    45         }
    46     }
    47     return d[t];
    48 }
    49 int dfs(int x,int a,int t) // a表示x点能接收的量
    50 {
    51     if(x==t||a==0)return a;
    52     int flow=0,f;//flow总的增量 f一条增广路的增量
    53     for(int &i=cur[x];i<g[x].size();i++)//cur[i] &引用修改其值 从上次考虑的弧
    54     {
    55         edge &e=edges[g[x][i]];
    56         if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.c-e.f),t))>0)    //按照层次图增广 满足容量限制
    57         {
    58             e.f+=f;
    59             edges[g[x][i]^1].f-=f;  //修改流量
    60             flow+=f;
    61             a-=f;
    62             if(a==0) break;
    63         }
    64     }
    65     return flow;
    66 }
    67 int maxflow(int s,int t)
    68 {
    69     int flow=0;
    70     while(bfs(s,t)!=-1) //等于-1代表构造层次图失败 结束
    71     {
    72         memset(cur,0,sizeof(cur));
    73         flow+=dfs(s,inf,t);
    74     }
    75     return flow;
    76 }
    77 int main()
    78 {
    79     int t,kase=1;
    80     scanf("%d",&t);
    81     while(t--)
    82     {
    83         scanf("%d%d",&n,&m);
    84         init();
    85         int u,v,c,f;
    86         for(int i=0;i<m;i++)
    87         {
    88             scanf("%d%d%d",&u,&v,&c);
    89             addedge(u,v,c);
    90         }
    91         printf("Case %d: %d
    ",kase++,maxflow(1,n));
    92     }
    93 }

     ISAP  gap优化版  性能比dinic 好一点

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=1e3+20,mod=1e9+7,inf=0x3f3f3f3f;
      4 typedef long long ll;
      5 struct Edge
      6 {
      7     int from,to,cap,flow;
      8     Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {}
      9 };
     10 int n,m;
     11 vector<Edge>edges;
     12 vector<int>G[maxn];
     13 int vis[maxn];
     14 int d[maxn],cur[maxn];
     15 int p[maxn],num[maxn];//比Dinic算法多了这两个数组,p数组标记父亲结点,num数组标记距离d[i]存在几个
     16 void init()
     17 {
     18     for(int i=0; i<=n; i++) G[i].clear();
     19     edges.clear();
     20     memset(d,-1,sizeof(d));
     21 }
     22 void addedge(int from,int to,int cap)
     23 {
     24     edges.push_back(Edge(from,to,cap,0));
     25     edges.push_back(Edge(to,from,0,0));
     26     int m=edges.size();
     27     G[from].push_back(m-2);
     28     G[to].push_back(m-1);
     29 }
     30 int Augumemt(int s,int t)
     31 {
     32     int x=t,a=inf;
     33     while(x!=s)//找最小的残量值
     34     {
     35         Edge&e=edges[p[x]];
     36         a=min(a,e.cap-e.flow);
     37         x=edges[p[x]].from;
     38     }
     39     x=t;
     40     while(x!=s)//增广
     41     {
     42         edges[p[x]].flow+=a;
     43         edges[p[x]^1].flow-=a;//更新反向边。
     44         x=edges[p[x]].from;
     45     }
     46     return a;
     47 }
     48 void bfs(int t)//逆向进行bfs
     49 {
     50     memset(vis,0,sizeof(vis));
     51     queue<int>q;
     52     q.push(t);
     53     d[t]=0;
     54     vis[t]=1;
     55     while(!q.empty())
     56     {
     57         int x=q.front();
     58         q.pop();
     59         int len=G[x].size();
     60         for(int i=0; i<len; i++)
     61         {
     62             Edge&e=edges[G[x][i]];
     63             if(!vis[e.from]&&e.cap>e.flow)
     64             {
     65                 vis[e.from]=1;
     66                 d[e.from]=d[x]+1;
     67                 q.push(e.from);
     68             }
     69         }
     70     }
     71 }
     72 
     73 int Maxflow(int s,int t)//根据情况前进或者后退,走到汇点时增广
     74 {
     75     int flow=0;
     76     bfs(t);
     77     memset(num,0,sizeof(num));
     78     for(int i=0; i<=n; i++)
     79         num[d[i]]++;
     80     int x=s;
     81     memset(cur,0,sizeof(cur));
     82     while(d[s]<n)
     83     {
     84         if(x==t)//走到了汇点,进行增广
     85         {
     86             flow+=Augumemt(s,t);
     87             x=s;//增广后回到源点
     88         }
     89         int ok=0;
     90         for(int i=cur[x]; i<G[x].size(); i++)
     91         {
     92             Edge& e=edges[G[x][i]];
     93             if(e.cap>e.flow&&d[x]==d[e.to]+1)
     94             {
     95                 ok=1;
     96                 p[e.to]=G[x][i];//记录来的时候走的边,即父边
     97                 cur[x]=i;
     98                 x=e.to;//前进
     99                 break;
    100             }
    101         }
    102         if(!ok)//走不动了,撤退
    103         {
    104             int m=n-1;//如果没有弧,那么m+1就是n,即d[i]=n
    105             for(int i=0; i<G[x].size(); i++)
    106             {
    107                 Edge& e=edges[G[x][i]];
    108                 if(e.cap>e.flow)
    109                     m=min(m,d[e.to]);
    110             }
    111             if(--num[d[x]]==0)break;//如果走不动了,且这个距离值原来只有一个,那么s-t不连通,这就是所谓的“gap优化”
    112             num[d[x]=m+1]++;
    113             cur[x]=0;
    114             if(x!=s)
    115                 x=edges[p[x]].from;//退一步,沿着父边返回
    116         }
    117     }
    118     return flow;
    119 }
    120 
    121 int main()
    122 {
    123     int t,kase=1;
    124     scanf("%d",&t);
    125     while(t--)
    126     {
    127         init();
    128         scanf("%d%d",&n,&m);
    129         for(int i=0; i<m; i++)
    130         {
    131             int from,to,cap;
    132             scanf("%d%d%d",&from,&to,&cap);
    133             addedge(from,to,cap);
    134         }
    135         printf("Case %d: %d
    ",kase++,Maxflow(1,n));
    136     }
    137     return 0;
    138 }

    ISAP算法 详解及其他版本参见https://blog.csdn.net/guhaiteng/article/details/52433239

  • 相关阅读:
    数据结构实验之图论六:村村通公路
    数据结构实验之图论二:基于邻接表的广度优先搜索遍历
    数据结构实验之图论二:基于邻接表的广度优先搜索遍历
    树结构练习——判断给定森林中有多少棵树
    树结构练习——判断给定森林中有多少棵树
    图结构练习——最短路径
    图结构练习——最短路径
    【郑轻】[1778]和尚特烦恼4——有多少战斗力
    【郑轻】[1778]和尚特烦恼4——有多少战斗力
    【郑轻】[1776]和尚特烦恼2——第几个素数
  • 原文地址:https://www.cnblogs.com/stranger-/p/9343611.html
Copyright © 2020-2023  润新知