• 网络流之最大流板子题


    在做最大流的题目之前,需要知道两个算法:EK与DINIC,但是鉴于我没有过多时间(特别懒),不想写基础知识与算法的推导,所以在此推荐两篇blog:(传送门1传送门2

    板子题1:

      poj1273lougu2740codevs1993.此题很明显,一入眼就知道这是一个纯正的最大流板子题,没什么好写的,注意的是,poj中的题目是有多组数据的,然而题目中却没有写,让我一脸懵逼的WA了好几次(我好菜我好菜),洛谷和codevs则没有这个问题。不废话了,上代码!!
    这是EK算法的:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cstdlib>
     7 #include<queue>
     8 using namespace std;
     9 int n,m,g[1005][1005],pre[2005],flow[2005];
    10 queue <int> q;
    11 int bfs(int s,int t)
    12 {
    13     while (!q.empty()) q.pop();
    14     for (int i=1; i<=n; i++) pre[i]=-1;
    15     pre[s]=0; q.push(s); flow[s]=20252025;
    16     while (!q.empty()){
    17         int x=q.front(); q.pop();
    18         if (x==t) break;
    19         for (int i=1; i<=n; i++)
    20             if (g[x][i]>0 && pre[i]==-1){
    21                 pre[i]=x;
    22                 flow[i]=min(flow[x],g[x][i]);
    23                 q.push(i);
    24             }
    25     }
    26     if (pre[t]==-1) return -1;
    27     else return flow[t];
    28 }
    29 int EK(int s,int t)
    30 {
    31     int increase=0,maxflow=0;
    32     while ((increase=bfs(s,t))!=-1){
    33         int k=t;
    34         while (k!=s){
    35             int xx=pre[k];
    36             g[xx][k]-=increase;
    37             g[k][xx]+=increase;
    38             k=xx;
    39         }
    40         maxflow+=increase;
    41     }
    42     return maxflow;
    43 }
    44 int main()
    45 {
    46     while (~scanf("%d%d",&m,&n)){
    47         memset(g,0,sizeof(g)); memset(flow,0,sizeof(flow));
    48         for (int i=1; i<=m; i++){
    49             int x,y,v;
    50             scanf("%d%d%d",&x,&y,&v);
    51             g[x][y]+=v;
    52         }
    53         int ans=EK(1,n);
    54         cout<<ans<<endl;
    55     }
    56     return 0;
    57 }

    这是DINIC算法的:(未加多组数据)

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cstdlib>
     7 #include<queue>
     8 using namespace std;
     9 queue<int> q;
    10 int n,m,x,y,z,maxflow,deep[505],vet[505],next[505],head[505],cur[505],dis[505],edgenum=-1;
    11 const int INF=1e9;
    12 void addedge(int u,int v,int t)
    13 {
    14     vet[++edgenum]=v;
    15     next[edgenum]=head[u];
    16     head[u]=edgenum;
    17     dis[edgenum]=t;
    18 }
    19 bool bfs(int s,int t)
    20 {
    21     memset(deep,0x7f,sizeof(deep));
    22     while (!q.empty()) q.pop();
    23     for (int i=1; i<=n; i++) cur[i]=head[i];
    24     deep[s]=0; q.push(s);
    25     while (!q.empty()){
    26         int x=q.front(); q.pop();
    27         for (int e=head[x]; e!=-1; e=next[e])
    28             if (deep[vet[e]]>INF && dis[e]){
    29                 deep[vet[e]]=deep[x]+1;
    30                 q.push(vet[e]);
    31             }
    32     }
    33     if (deep[t]<INF) return true; else return false;
    34 }
    35 int dfs(int now,int t,int limit)
    36 {
    37     if (!limit || now==t) return limit;
    38     int flow=0,f;
    39     for (int e=cur[now]; e!=-1; e=next[e]){
    40         cur[now]=e;
    41         if ((deep[vet[e]]==(deep[now]+1)) && (f=dfs(vet[e],t,min(limit,dis[e])))){
    42             flow+=f; limit-=f;
    43             dis[e]-=f;
    44             dis[e^1]+=f;
    45             if (!limit) break;
    46         }
    47     }
    48     return flow;
    49 }
    50 void dinic(int s,int t)
    51 {
    52     while (bfs(s,t)) maxflow+=dfs(s,t,INF);
    53 }
    54 int main()
    55 {
    56     scanf("%d%d",&m,&n);
    57     memset(head,-1,sizeof(head));
    58     for (int i=1; i<=m; i++){
    59         int x,y,v;
    60         scanf("%d%d%d",&x,&y,&v);
    61         addedge(x,y,v); addedge(y,x,0);
    62     }
    63     dinic(1,n);
    64     cout<<maxflow<<endl;
    65     return 0;
    66 }

    板子题2:

      poj1459.这一道题目看一眼题面,稍加思考便可知此为最大流算法,我们只需要建立一个超级源点与超级汇点,将超级源点与发电站相连,超级汇点与用电处相连,跑一遍dinic便可。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cstdlib>
     7 #include<queue>
     8 using namespace std;
     9 queue<int> q;
    10 const int INF=1e9;
    11 int vet[30005],next[30005],head[30005],dis[300005],cur[30005],edgenum=-1,n,np,nc,m,deep[30005],maxflow,sp,fp;
    12 void addedge(int u,int v,int t)
    13 {
    14     vet[++edgenum]=v;
    15     next[edgenum]=head[u];
    16     head[u]=edgenum;
    17     dis[edgenum]=t;
    18 }
    19 bool bfs(int s,int t)
    20 {
    21     for (int i=1; i<=n; i++) cur[i]=head[i];
    22     memset(deep,0x7f,sizeof(deep)); deep[s]=0;
    23     while (!q.empty()) q.pop(); q.push(s);
    24     while (!q.empty()){
    25         int x=q.front(); q.pop();
    26         for (int e=head[x]; e!=-1; e=next[e])
    27             if (deep[vet[e]]>INF && dis[e]){
    28                 deep[vet[e]]=deep[x]+1;
    29                 q.push(vet[e]);
    30             }
    31     }
    32     if (deep[t]>INF) return false; else return true;
    33 }
    34 int dfs(int now,int t,int limit)
    35 {
    36     int flow=0,f;
    37     if (!limit || now==t) return limit;
    38     for (int e=cur[now]; e!=-1; e=next[e]){    
    39         cur[now]=e;
    40         if ((deep[vet[e]]==deep[now]+1) && (f=dfs(vet[e],t,min(limit,dis[e])))){
    41             dis[e]-=f; limit-=f;
    42             flow+=f; dis[e^1]+=f;
    43             if (!limit) break;
    44         }
    45     }
    46     return flow;
    47 }
    48 void dinic(int s,int t)
    49 {
    50     while (bfs(s,t)) maxflow+=dfs(s,t,INF);
    51 }
    52 int main()
    53 {
    54     while (~scanf("%d%d%d%d",&n,&np,&nc,&m)){
    55         memset(head,-1,sizeof(head)); memset(next,-1,sizeof(next)); memset(dis,0,sizeof(dis)); edgenum=-1;
    56         memset(cur,0,sizeof(cur)); char ch; maxflow=0;
    57         for (int i=1; i<=m; i++){
    58             int x,y,z;
    59             cin>>ch>>x>>ch>>y>>ch>>z; x++; y++;
    60             addedge(x,y,z); addedge(y,x,0);
    61         }
    62         sp=n+1; fp=n+2; n+=2;
    63         for (int i=1; i<=np; i++){
    64             int x,y;
    65             cin>>ch>>x>>ch>>y; x++;
    66             addedge(sp,x,y); addedge(x,sp,0);
    67         }
    68         for (int i=1; i<=nc; i++){
    69             int x,y;
    70             cin>>ch>>x>>ch>>y; x++;
    71             addedge(x,fp,y); addedge(fp,x,0);
    72         }
    73         dinic(sp,fp);
    74         cout<<maxflow<<endl;
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    鸡啄米vc++2010系列46(Ribbon界面开发:使用更多控件并为控件添加消息处理函数)
    鸡啄米vc++2010系列45(Ribbon界面开发:为Ribbon Bar添加控件)
    鸡啄米vc++2010系列44(Ribbon界面开发:创建Ribbon样式的应用程序框架)
    鸡啄米vc++2010系列43(MFC常用类:定时器Timer)
    鸡啄米vc++2010系列42(MFC常用类:CTime类和CTimeSpan类)
    鸡啄米vc++2010系列41(MFC常用类:CString类)
    pcl库的配置
    鸡啄米vc++2010系列40(文档、视图和框架:分割窗口)
    鸡啄米vc++2010系列39(文档、视图和框架:各对象之间的关系)
    c 函数传入数组。
  • 原文地址:https://www.cnblogs.com/wangyh1008/p/9355098.html
Copyright © 2020-2023  润新知