zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Infopath Notify 弹出提示信息
    window.showModalDialog 返回值
    【转】获得正文内容中的所有img标签的图片路径
    Json Datable Convert
    Sharepoint 列表 附件 小功能
    Surgey 权限更改
    SQL 触发器用于IP记录转换
    Caml语句 查询分配给当前用户及当前组
    jquery 1.3.2 auto referenced when new web application in VSTS2010(DEV10)
    TFS diff/merge configuration
  • 原文地址:https://www.cnblogs.com/stranger-/p/9343611.html
Copyright © 2011-2022 走看看