zoukankan      html  css  js  c++  java
  • 经典的最大流题POJ1273(网络流裸题)

    http://poj.org/problem?id=1273

    Drainage Ditches
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions:87219   Accepted: 33916

    Description

    Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by water for awhile and takes quite a long time to regrow. Thus, Farmer John has built a set of drainage ditches so that Bessie's clover patch is never covered in water. Instead, the water is drained to a nearby stream. Being an ace engineer, Farmer John has also installed regulators at the beginning of each ditch, so he can control at what rate water flows into that ditch. 
    Farmer John knows not only how many gallons of water each ditch can transport per minute but also the exact layout of the ditches, which feed out of the pond and into each other and stream in a potentially complex network. 
    Given all this information, determine the maximum rate at which water can be transported out of the pond and into the stream. For any given ditch, water flows in only one direction, but there might be a way that water can flow in a circle. 

    Input

    The input includes several cases. For each case, the first line contains two space-separated integers, N (0 <= N <= 200) and M (2 <= M <= 200). N is the number of ditches that Farmer John has dug. M is the number of intersections points for those ditches. Intersection 1 is the pond. Intersection point M is the stream. Each of the following N lines contains three integers, Si, Ei, and Ci. Si and Ei (1 <= Si, Ei <= M) designate the intersections between which this ditch flows. Water will flow through this ditch from Si to Ei. Ci (0 <= Ci <= 10,000,000) is the maximum rate at which water will flow through the ditch.

    Output

    For each case, output a single integer, the maximum rate at which water may emptied from the pond.

    Sample Input

    5 4
    1 2 40
    1 4 20
    2 4 20
    2 3 30
    3 4 10
    

    Sample Output

    50

    现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条水渠,给出这n条水渠所连接的池塘和所能流过的水量,求水渠中所能流过的水的最大容量.一道基础的最大流题目。

    ——其他练习题 POJ3436 、

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <bitset>
      5 #include <cmath>
      6 #include <cctype>
      7 #include <iostream>
      8 #include <algorithm>
      9 #include <string>
     10 #include <vector>
     11 #include <queue>
     12 #include <map>
     13 #include <set>
     14 #include <sstream>
     15 #include <iomanip>
     16 using namespace std;
     17 typedef long long ll;
     18 typedef unsigned long long ull;
     19 const ll inff = 0x3f3f3f3f3f3f3f3f;
     20 #define FOR(i,a,b) for(int i(a);i<=(b);++i)
     21 #define FOL(i,a,b) for(int i(a);i>=(b);--i)
     22 #define REW(a,b) memset(a,b,sizeof(a))
     23 #define inf int(0x3f3f3f3f)
     24 #define si(a) scanf("%d",&a)
     25 #define sl(a) scanf("%I64d",&a)
     26 #define sd(a) scanf("%lf",&a)
     27 #define ss(a) scanf("%s",a)
     28 #define mod ll(998244353)
     29 #define pb push_back
     30 #define eps 1e-6
     31 #define lc d<<1
     32 #define rc d<<1|1
     33 #define Pll pair<ll,ll>
     34 #define P pair<int,int>
     35 #define pi acos(-1)
     36 const int N=100008,M=100008;
     37 int head[N],tot,n,m,a,b,c;
     38 struct node{
     39 int next,c,to;}e[M];
     40 struct max_flow{
     41     int S,T,n;
     42     int lev[N],q[N],cur[N],f;
     43     void init(int _s,int _t)
     44     {
     45         tot=0;S=_s,T=_t,n=T+1;
     46         FOR(i,0,n) head[i]=-1;
     47     }
     48     void add(int a,int b,int c)
     49     {
     50         e[tot].next=head[a];
     51         e[tot].to=b;
     52         e[tot].c=c;
     53         head[a]=tot++;
     54     }
     55     void Add(int a,int b,int c)
     56     {
     57         add(a,b,c);
     58         add(b,a,0);
     59     }
     60     int bfs()
     61     {
     62         FOR(i,0,n) lev[i]=0;
     63         lev[S]=1,f=0,q[f++]=S;
     64         FOR(i,0,f-1)
     65         {
     66             int u=q[i];
     67             for(int i=head[u];i!=-1;i=e[i].next)
     68              if(lev[e[i].to]==0&&e[i].c>0)
     69              {
     70                  int to=e[i].to;
     71                  lev[to]=lev[u]+1;
     72                  q[f++]=to;
     73                  if(to==T) return 1;
     74              }
     75         }
     76         return 0;
     77     }
     78     int dfs(int u,int f)
     79     {
     80         if(u==T) return f;
     81         int tag=0,c;
     82         for(int &i=cur[u];i!=-1;i=e[i].next)
     83         {
     84             int to=e[i].to;
     85             if(e[i].c>0&&lev[to]==lev[u]+1)
     86             {
     87                 c=dfs(to,min(f-tag,e[i].c));
     88                 e[i].c-=c;
     89                 e[i^1].c+=c;
     90                 tag+=c;
     91                 if(tag==f) return tag;
     92             }
     93         }
     94         return tag;
     95     }
     96     int slove()
     97     {
     98         int ans=0;
     99         while(bfs())
    100         {
    101             FOR(i,0,n) cur[i]=head[i];
    102             ans+=dfs(S,inf);
    103         }
    104         return ans;
    105     }
    106 }flow;
    107 int main()
    108 {
    109     cin.tie(0);
    110     cout.tie(0);
    111     while(~scanf("%d%d",&m,&n))
    112     {
    113         flow.init(1,n);
    114         while(m--)
    115         {
    116             si(a),si(b),si(c);
    117             flow.Add(a,b,c);
    118         }
    119         cout<<flow.slove()<<endl;
    120     }
    121     return 0;
    122 }
    View Code

    https://blog.csdn.net/huzhengnan/article/details/7766446

    最大流的一些板子

    https://blog.csdn.net/wjf_wzzc/article/details/24820525

    sap:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<cstdlib>
      6 #include<string>
      7 #include<queue>
      8 #include<algorithm>
      9 using namespace std;
     10  
     11 const int N=100010;
     12 const int M=400010;
     13 const int inf=0xfffffff;
     14  
     15 int n,m,cnt;
     16  
     17 struct Edge{
     18     int v , cap , next;
     19 } edge[M];
     20  
     21 int head[N],pre[N],d[N],numd[N];//分别为链表的头指针,每个点的前驱,每个点的d值,以及标号为d[i] 的点的个数
     22 int cur_edge[N];//从每个点出发满足d[i] = d[j] + 1的边的地址 , 插入边时的计数,源点与汇点
     23  
     24 void addedge(int u,int v,int c){
     25  
     26     edge[cnt].v = v;
     27     edge[cnt].cap = c;
     28     edge[cnt].next = head[u];
     29     head[u] = cnt++;
     30  
     31     edge[cnt].v = u;
     32     edge[cnt].cap = 0;
     33     edge[cnt].next = head[v];
     34     head[v] = cnt++;
     35 }
     36  
     37 void bfs(int s){    //先用广度优先算出每个点的d值
     38     memset(numd,0,sizeof(numd));
     39     for(int i=1; i<=n; i++)
     40         numd[ d[i] = n ]++;
     41     d[s] = 0;
     42     numd[n]--;
     43     numd[0]++;
     44     queue<int> Q;
     45     Q.push(s);
     46  
     47     while(!Q.empty()){
     48         int v=Q.front();
     49         Q.pop();
     50  
     51         int i=head[v];
     52         while(i != -1){
     53             int u=edge[i].v;
     54  
     55             if(d[u]<n){
     56                 i=edge[i].next;
     57                 continue ;
     58             }
     59  
     60             d[u]=d[v]+1;
     61             numd[n]--;
     62             numd[d[u]]++;
     63             Q.push(u);
     64             i=edge[i].next;
     65         }
     66     }
     67 }
     68 
     69 int SAP(int s,int t){
     70     for(int i = 1; i <= n; i++)
     71         cur_edge[i] = head[i];   //当前满足d[i] = d[j] + 1的边的为第一条边
     72     int max_flow=0;
     73     bfs(t);
     74     int u = s ;//从源点搜一条到汇点的增广路
     75     while(d[s]<n){//就算所有的点连成一条线源点的d值也是最多是n-1
     76         if(u == t){//如果找到一条增广路径
     77             int cur_flow = inf,neck;//找到那条瓶颈边
     78             for(int from = s; from != t; from = edge[cur_edge[from]].v){
     79                 if(cur_flow > edge[cur_edge[from]].cap){
     80                     neck = from;
     81                     cur_flow = edge[cur_edge[from]].cap;
     82                 }
     83             }
     84  
     85             for(int from = s; from != t; from = edge[cur_edge[from]].v){    //修改增广路上的边的容量
     86                 int tmp = cur_edge[from];
     87                 edge[tmp].cap -= cur_flow;
     88                 edge[tmp^1].cap += cur_flow;
     89             }
     90             max_flow += cur_flow;//累加计算最大流
     91             u = neck;//下一次搜索直接从瓶颈边的前一个节点搜起
     92         }
     93  
     94         int i;
     95         for(i = cur_edge[u]; i != -1; i = edge[i].next) //从当前点开始找一条允许弧
     96             if(edge[i].cap && d[u] == d[edge[i].v]+1)//如果找到跳出循环
     97                 break;
     98  
     99         if(i!=-1){//找到一条允许弧
    100             cur_edge[u] = i;//从点u出发的允许弧的地址
    101             pre[edge[i].v] = u;//允许弧上下一个点的前驱为u
    102             u = edge[i].v;//u变成下一个点继续搜直到搜出一条增广路
    103         }
    104         else{//如果没有搜到允许弧
    105             numd[d[u]]--; //d[u]将被修改所以numd[d[u]]减一
    106             if(!numd[d[u]]) break;  //如果没有点的d值为d[u]则不可能再搜到增广路结束搜索
    107             cur_edge[u] = head[u];  //当前点的允许弧为第一条边
    108             int tmp = n;
    109             for(int j = head[u]; j != -1; j = edge[j].next) //搜与u相连的点中d值最小的
    110                 if(edge[j].cap && tmp > d[edge[j].v])
    111                     tmp = d[edge[j].v];
    112  
    113             d[u] = tmp+1; //修改d[u]
    114             numd[d[u]]++;
    115             if(u != s)
    116                 u = pre[u];//从u的前驱搜,因为从u没有搜到允许弧
    117         }
    118     }
    119     return max_flow;
    120 }
    121 inline void pre_init(){ 
    122     cnt = 0;
    123     memset(head, -1, sizeof head);  
    124 } 
    125 
    126 void mapping(){
    127     int u, v, w;
    128     for(int i = 1; i <= m; ++i){  
    129         scanf("%d %d %d", &u, &v, &w); 
    130         addedge(u, v, w);  
    131     }
    132 }
    133 
    134 int main(){
    135     while(~scanf("%d%d",&m,&n)){
    136         pre_init();
    137         mapping();
    138         int s,t;
    139         s = 1;t = n;
    140         int ans = SAP(s,t);
    141         printf("%d
    ",ans);
    142     }
    143     return 0;
    144 }
    View Code

    dinic:

     1 //dinic
     2 
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <string.h>
     6 #include <cstdio>
     7 #include <queue>
     8 using namespace std;
     9 const int inf = 0x3f3f3f3f;
    10 const int maxn = 205;
    11 const int maxm = maxn*maxn;
    12 struct node{int w; int v, next;} edge[maxm];
    13 int pre[maxn], rec[maxn], head[maxn], block[maxn];
    14 int dis[maxn];
    15 int n, m, no;
    16 int S, T;
    17 queue<int> q;
    18 inline void init(){
    19     no = 0;
    20     memset(head, -1, sizeof head);
    21 }
    22 inline void add(int u, int v, int w){
    23     edge[no].v = v; edge[no].w = w;
    24     edge[no].next = head[u]; head[u] = no++;
    25     edge[no].v = u; edge[no].w = 0;
    26     edge[no].next = head[v]; head[v] = no++;
    27 }
    28 void reset(int S, int T){
    29     memset(dis, 0x3f, sizeof dis);
    30     memset(block, 0, sizeof block);
    31     q.push(S); dis[S] = 0;
    32     while(!q.empty()){
    33         int top = q.front(); q.pop();
    34         for(int k = head[top]; k != -1; k = edge[k].next)
    35         if(dis[edge[k].v] == inf && edge[k].w)
    36             dis[edge[k].v] = dis[top]+1, q.push(edge[k].v);
    37     }
    38 }
    39 int dinic(int S, int T){
    40     int ans = 0, flow = inf;
    41     int top = S;
    42     reset(S, T); pre[S] = S;
    43     while(dis[T] != inf){
    44         int k, tmp;
    45         for(k = head[top]; k != -1; k = edge[k].next){
    46             if(edge[k].w && dis[edge[k].v]==dis[top]+1 && 
    47             !block[edge[k].v]) break;
    48         }
    49         if(k != -1){
    50             tmp = edge[k].v;
    51             flow = min(flow, edge[k].w);
    52             pre[tmp] = top, rec[tmp] = k;
    53             top = tmp;
    54             if(top == T){
    55                 ans += flow; tmp = -1;
    56                 for(; top != S; top = pre[top]){
    57                     edge[rec[top]].w -= flow;
    58                     edge[rec[top]^1].w += flow;
    59                     if(!edge[rec[top]].w) tmp = top;
    60                 }
    61                 flow = inf;
    62                 if(tmp != -1){
    63                     top = pre[tmp];
    64                     for(; top != S; top = pre[top])
    65                     flow = min(flow, edge[rec[top]].w);
    66                     top = pre[tmp];
    67                 }
    68             }
    69         }
    70         else{
    71             block[top] = 1;
    72             top = pre[top];
    73             if(block[S]) reset(S, T);
    74         }
    75     }
    76     return ans;
    77 }
    78 void mapping(){
    79     int u, v, w;
    80     for(int i = 1; i <= m; ++i){
    81         scanf("%d %d %d", &u, &v, &w);
    82         add(u, v, w);
    83     }
    84 }
    85 int main(){
    86     while(~scanf("%d %d", &m, &n)){
    87         S = 1, T = n;
    88         init();
    89         mapping();
    90         printf("%d
    ", dinic(S, T));
    91     }
    92     return 0;
    93 }
    View Code

    感谢https://www.cnblogs.com/Asumi/p/9751117.html

    【最大流之Dinic算法】POJ1273 【 & 当前弧优化 & 】

    https://www.cnblogs.com/DF-yimeng/p/8583698.html

    //dinic

    #include <algorithm>
    #include <iostream>
    #include <string.h>
    #include <cstdio>
    #include <queue>
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const int maxn = 205;
    const int maxm = maxn*maxn;
    struct node
    {
        int w;
        int v, next;
    } edge[maxm];
    int pre[maxn], rec[maxn], head[maxn], block[maxn];
    int dis[maxn];
    int n, m, no;
    int S, T;
    queue<int> q;
    inline void init()
    {
        no = 0;
        memset(head, -1, sizeof head);
    }
    inline void add(int u, int v, int w)
    {
        edge[no].v = v;
        edge[no].w = w;
        edge[no].next = head[u];
        head[u] = no++;
        edge[no].v = u;
        edge[no].w = 0;
        edge[no].next = head[v];
        head[v] = no++;
    }
    void reset(int S, int T)
    {
        memset(dis, 0x3f, sizeof dis);
        memset(block, 0, sizeof block);
        q.push(S);
        dis[S] = 0;
        while(!q.empty())
        {
            int top = q.front();
            q.pop();
            for(int k = head[top]; k != -1; k = edge[k].next)        if(dis[edge[k].v] == inf && edge[k].w)            dis[edge[k].v] = dis[top]+1, q.push(edge[k].v);
        }
    }
    int dinic(int S, int T)
    {
        int ans = 0, flow = inf;
        int top = S;
        reset(S, T);
        pre[S] = S;
        while(dis[T] != inf)
        {
            int k, tmp;
            for(k = head[top]; k != -1; k = edge[k].next)
            {
                if(edge[k].w && dis[edge[k].v]==dis[top]+1 &&             !block[edge[k].v]) break;
            }
            if(k != -1)
            {
                tmp = edge[k].v;
                flow = min(flow, edge[k].w);
                pre[tmp] = top, rec[tmp] = k;
                top = tmp;
                if(top == T)
                {
                    ans += flow;
                    tmp = -1;
                    for(; top != S; top = pre[top])
                    {
                        edge[rec[top]].w -= flow;
                        edge[rec[top]^1].w += flow;
                        if(!edge[rec[top]].w) tmp = top;
                    }
                    flow = inf;
                    if(tmp != -1)
                    {
                        top = pre[tmp];
                        for(; top != S; top = pre[top])                    flow = min(flow, edge[rec[top]].w);
                        top = pre[tmp];
                    }
                }
            }
            else
            {
                block[top] = 1;
                top = pre[top];
                if(block[S]) reset(S, T);
            }
        }
        return ans;
    }
    void mapping()
    {
        int u, v, w;
        for(int i = 1; i <= m; ++i)
        {
            scanf("%d %d %d", &u, &v, &w);
            add(u, v, w);
        }
    }
    int main()
    {
        while(~scanf("%d %d", &m, &n))
        {
            S = 1, T = n;
            init();
            mapping();
            printf("%d
    ", dinic(S, T));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    第八次作业-谈谈Java web学习小结
    第七周作业--可行性研究与程序系统的结构
    第六次作业-数据库连接
    第五次作业-系统实现可能需要用到的技术,及学习相关技术的心得
    第四次作业-软件需求分析过程与需求分类
    第三次作业-前端与后台数据交换问题
    第二次作业-软件工作量估算方法
    第一次作业
    捣鼓一个Ajax请求管理器
    动动手,写个knockout的分页模板
  • 原文地址:https://www.cnblogs.com/DWVictor/p/10225010.html
Copyright © 2011-2022 走看看