zoukankan      html  css  js  c++  java
  • 婚车1667(最大流模板题)

    题目描述

    航哥是个土豪,他想在让城市布满他的婚车。但是城市的每条道路单位时间能通过的婚车是有限的,超出则会造成拥堵。他在1号点屯了足够数量的车子,他想知道从城市1号点派出婚车去n号点迎接新娘,在买通交警只允许他的婚车在车道上行驶的条件下,足够多时间之后,n号点单位时间内最多能容纳多少量婚车。

    输入

    第一行两个整数,n和m,n为点数,m为边数,点的标号为1~n。

    接下来M行,每行三个整数a, b, c, 表示城市中两个点之间有一条单位时间最多通行c辆车的道路。

    建图连边之前请注意审题……

    1n10001≤n≤1000

    1m1000001≤m≤100000

    1a,bn,ab1≤a,b≤n,a≠b

    1c101≤c≤10

    输出

    输出一个整数,点n处单位时间内最多接受的婚车数量。

    输入样例

    4 6
    1 2 5
    1 3 2
    1 4 3
    2 3 3
    2 4 3
    3 4 10

    输出样例

    10

    http://blog.sina.com.cn/s/blog_6cf509db0100uy5n.html

    最大流模板题,需要注意的是路是双向的,r[a][b]=c,r[b][a]=c;

    用EK算法实现,邻接矩阵存储图。

    找增广路的过程:

    bfs本身是用作遍历图的算法,但在遍历的同时会生成一条从起点至某一点的路径(且该路径始终是当前图中从起点到该点的最短路径,EK利用这一特点可以按一定顺序寻找增光路)

    那么如何在bfs遍历过程中找到这条路径呢?考虑bfs的详细过程,是一层一层辐射状散开寻找点的,且到达每一个点之前的前一个点都是唯一的,因此可以用一维数组pre存储这个路径(前驱),pre[i]=p表示路径上点i的前一个点为p,每次只要遍历到汇点t就结束bfs(可能此时bfs并未遍历完,但后边的结果我们都不需要了)。至此就找到一条增广路。

    之后我们再拿着找到的增广路对残余网络进行更新,再去寻找新的增广路直到找不到增广路为止。

    (另外注意用队列实现bfs时,push后就要马上把visit置1,否则会由重复元素进入队列)

    ac代码

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include<algorithm>
     5 #include<queue>
     6 using namespace std;
     7 
     8 const int maxn=1007;
     9 const int inf=0x7fffffff;
    10 
    11 int r[maxn][maxn];
    12 bool visit[maxn];
    13 int pre[maxn];
    14 int m,n;
    15 //bfs寻找增光路,找到返回ture
    16 bool bfs(int s,int t){
    17     queue<int> q;
    18     int p;
    19     memset(visit,false,sizeof(visit));
    20     memset(pre,-1,sizeof(pre));
    21     pre[s]=s;
    22     q.push(s);
    23     visit[s]=true;
    24     while(!q.empty()){
    25         p=q.front();
    26         q.pop();
    27         //认为节点的数组下标从1开始,用邻接矩阵存储
    28         for(int i=1;i<=n;++i){
    29             if(r[p][i]>0&&!visit[i]){
    30                 visit[i]=true;
    31                 pre[i]=p;
    32                 if(i==t)
    33                     return true;
    34                 q.push(i);
    35             }
    36         }
    37     }
    38     return false;
    39 }
    40 int EK(int s,int t){
    41     //inc表示增广路可增加的流量
    42     int maxflow=0,inc;
    43     while(bfs(s,t)){
    44         //坑:每次循环一开始都要置inc为inf
    45         inc=inf;
    46         for(int i=t;i!=s;i=pre[i]){
    47             if(inc>r[pre[i]][i]){
    48                 inc=r[pre[i]][i];
    49             }
    50         }
    51         //这里要求如果两点之间没有边时权重r初始化为0
    52         for(int i=t;i!=s;i=pre[i]){
    53 
    54             r[pre[i]][i]-=inc;
    55             r[i][pre[i]]+=inc;
    56         }
    57         maxflow+=inc;
    58     }
    59     return maxflow;
    60 }
    61 void startEK(){
    62     int a,b,c;
    63     int ans;
    64 
    65     //while(~scanf("%d%d",&n,&m)){
    66         scanf("%d%d",&n,&m);
    67         memset(r,0,sizeof(r));
    68         for(int i=0;i<m;++i){
    69             scanf("%d%d%d",&a,&b,&c);
    70             r[a][b]+=c;
    71             //看是否为双向路
    72             r[b][a]=c;
    73         }
    74         //默认s=1,t=n
    75         ans=EK(1,n);
    76         printf("%d
    ",ans);
    77     //}
    78     return;
    79 }
    80 int main()
    81 {
    82     startEK();
    83 }

    最大流模板(邻接矩阵)

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include<algorithm>
     5 #include<queue>
     6 using namespace std;
     7 
     8 const int maxn=1007;
     9 const int inf=0x7fffffff;
    10 
    11 int r[maxn][maxn];
    12 bool visit[maxn];
    13 int pre[maxn];
    14 int m,n;
    15 //bfs寻找增光路,找到返回ture
    16 bool bfs(int s,int t){
    17     queue<int> q;
    18     int p;
    19     memset(visit,false,sizeof(visit));
    20     memset(pre,-1,sizeof(pre));
    21     pre[s]=s;
    22     q.push(s);
    23     visit[s]=true;
    24     while(!q.empty()){
    25         p=q.front();
    26         q.pop();
    27         //认为节点的数组下标从1开始,用邻接矩阵存储
    28         for(int i=1;i<=n;++i){
    29             if(r[p][i]>0&&!visit[i]){
    30                 visit[i]=true;
    31                 pre[i]=p;
    32                 if(i==t)
    33                     return true;
    34                 q.push(i);
    35             }
    36         }
    37     }
    38     return false;
    39 }
    40 int EK(int s,int t){
    41     //inc表示增广路可增加的流量
    42     int maxflow=0,inc;
    43     while(bfs(s,t)){
    44         //坑:每次循环一开始都要置inc为inf
    45         inc=inf;
    46         for(int i=t;i!=s;i=pre[i]){
    47             if(inc>r[pre[i]][i]){
    48                 inc=r[pre[i]][i];
    49             }
    50         }
    51         //这里要求如果两点之间没有边时权重r初始化为0
    52         for(int i=t;i!=s;i=pre[i]){
    53 
    54             r[pre[i]][i]-=inc;
    55             r[i][pre[i]]+=inc;
    56         }
    57         maxflow+=inc;
    58     }
    59     return maxflow;
    60 }
    61 void startEK(){
    62     int a,b,c;
    63     int ans;
    64 
    65     while(~scanf("%d%d",&n,&m)){
    66         
    67         memset(r,0,sizeof(r));
    68         for(int i=0;i<m;++i){
    69             scanf("%d%d%d",&a,&b,&c);
    70             r[a][b]+=c;
    71             //看是否为双向路
    72             //r[b][a]=c;
    73         }
    74         //默认s=1,t=n
    75         ans=EK(1,n);
    76         printf("%d
    ",ans);
    77     }
    78     return;
    79 }
    80 int main()
    81 {
    82     startEK();
    83 }
     
  • 相关阅读:
    流程控制之if判断
    各种运算符
    输入和输出
    垃圾回收机制(详细)
    3/5 作业
    3/4 作业
    数据类型
    变量
    Checkout 显示 URL /../../.. 不存在
    Tomcat8 访问 manager App 失败
  • 原文地址:https://www.cnblogs.com/loganlzj/p/10097829.html
Copyright © 2011-2022 走看看