poj1273Drainage Ditches

简介:

#include<iostream>
/*
    题意:就是寻找从源点到汇点的最大流!
          要注意的是每两个点的流量可能有多个,也就是说有重边,所以要把两个点的所有的流量都加起来
          就是这两个点之间的流量了!
          
    思路:建图之后直接套用最大流算法(EK, 或者是Dinic算法) 图解Dinic算法流程!
*/ 
#include<queue>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define INF 0x3f3f3f3f3f3f3f3f
#define N 205 
using namespace std;
typedef long long LL;
LL cap[N][N];

int m, n;
LL maxFlow;
int d[N];
queue<int>q;

bool bfs(){
    q.push(1);
    memset(d, 0, sizeof(d));
    d[1]=1;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int v=1; v<=n; ++v)
           if(!d[v] && cap[u][v]>0){
              d[v]=d[u]+1;
              q.push(v);
           }
    } 
    if(!d[n])  return false;
    return true;
}

LL dfs(int u, LL flow){
    if(u==n) return flow;
    for(int v=1; v<=n; ++v)
       if(d[v]==d[u]+1 && cap[u][v]>0){
           LL a=dfs(v, min(flow, cap[u][v]));
           if(a==0) continue;//如果a==0 说明没有找到从起点到汇点的增广路, 然后换其他路接着寻找! 
           cap[u][v]-=a;
           cap[v][u]+=a;
           return a;
       } 
    return 0;
}

void Dinic(){
    LL flow;
     while(bfs()){//利用bfs构造好层次图,这样dfs在寻找阻塞流的时候,就不会盲目的寻找了! 
        while(flow=dfs(1, INF)) maxFlow+=flow;//利用构造好的层次图不断的寻找阻塞流! 
    }
}

int main(){
    while(scanf("%d%d", &m, &n)!=EOF){
        memset(cap, 0, sizeof(cap));
        while(m--){
            int u, v;
            LL w;
            scanf("%d%d%lld", &u, &v, &w);
            cap[u][v]+=w;
        }
        maxFlow=0;
        Dinic();
        printf("%lld\n", maxFlow);
    }
    return 0;
} 
//EK算法同样搞定
#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef __int64 LL;
LL cap[205][205];
int pre[205];
LL a[205];
int m, n;
queue<int>q;
LL maxFlow;
bool spfa(){
   while(!q.empty()) q.pop();
   memset(a, 0, sizeof(a));
   q.push(1);
   a[1]=INF;
   while(!q.empty()){
      int u=q.front();
      q.pop();
      for(int v=1; v<=n; ++v)                  
         if(!a[v] && cap[u][v]>0){
            pre[v]=u;
            a[v]=min(a[u], cap[u][v]);
            q.push(v);         
         }
      if(a[n]) break;
   } 
   if(!a[n]) return false;
   return true;
}

void EK(){
    maxFlow=0;
    while(spfa()){
       int u=n;
       maxFlow+=a[n];
       while(u!=1){
           cap[pre[u]][u]-=a[n];
           cap[u][pre[u]]+=a[n];            
           u=pre[u];
       }         
    }     
}
int main(){
   while(scanf("%d%d", &m, &n)!=EOF){
         memset(cap, 0, sizeof(cap));
         while(m--){
            int u, v;
            LL w;
            scanf("%d%d%I64d", &u, &v, &w);
            cap[u][v]+=w;  
         }
         EK();
         printf("%I64d\n", maxFlow);
   }
   return 0;    
}

目录
相关文章
poj 3298 数状数组
题目大意是一条大街上住着n个乒乓球爱好者,他们的水平高低用一个数值表示,他们经常举办比赛,比赛要三个人,一人当裁判。对裁判是有一定要求的,裁判的水平必须介于两选手之间且必须住他们中间,计算可以举办多少场比赛
41 0
POJ 1804
题目:http://poj.org/problem?id=1804 大意:给你一串数字,排序。求出最少的交换次数  \ 我用归并做的 #include #include using namespace std; int aa[500010],bb[500010]; long lon...
699 0
|
测试技术
poj-1218 THE DRUNK JAILER 喝醉的狱卒
自己去看看原题; 题目大意: 就是一个狱卒喝醉了,他第一趟吧所有的监狱都带开,第二趟把能把二整除的监狱关闭,第三趟操作能把三整除的监狱; 求最后能逃跑的罪犯数 输入第一个数是代表 测试数据组数 每个数据代表狱卒来回的次数 当作开关问题即可 #include using names...
1008 0
|
机器学习/深度学习 算法