• POJ 3204 Ikki's Story I


    题意:给出一个流网络,问有仅将一条边的容量增大可以使得最大流增大的边有多少条。

    首先,肯定将是满流的边的容量增大才可能使得最大流增大。但是这些满流的边不一定能是最小割,即使它出现在最小割中,把它的容量增大也不一定能使最大流增大。那么考虑一下求完最大流后不能增广的原因,或者说,怎么样才能在残量网络中增广呢?从S出发,dfs出所有满流的正向边,给dfs经过的点标上f1。再从T出发,逆向dfs出所有满流的边,给dfs经过的点标上f2。那么如果有一条边是这样的:满流且有f1标记和f2标记,那么增加它的容量,残量网络就又可以增广了,最大流会增加,因此这样的边就是我们需要寻找的边。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define INF 1<<30
      6 #define maxn 510
      7 #define maxm 100000
      8 using namespace std;
      9 
     10 int u[maxm],v[maxm],next[maxm],w[maxm];
     11 int first[maxn],d[maxn],work[maxn],q[maxn];
     12 int e,S,T;
     13 bool f1[maxn],f2[maxn];
     14 int n,m;
     15 void init(){
     16     memset(first,-1,sizeof(first));
     17     e = 0;
     18 }
     19 
     20 void add_edge(int a,int b,int c){
     21     u[e] = a;v[e] = b;next[e] = first[a];w[e] = c;first[a] = e++;
     22     u[e] = b;v[e] = a;next[e] = first[b];w[e] = 0;first[b] = e++;
     23 }
     24 
     25 int bfs(){
     26     int rear = 0;
     27     memset(d,-1,sizeof(d));
     28     d[S] = 0;q[rear++] = S;
     29     for(int i = 0;i < rear;i++){
     30         for(int j = first[q[i]];j != -1;j = next[j])
     31             if(w[j] && d[v[j]] == -1){
     32                 d[v[j]] = d[q[i]] + 1;
     33                 q[rear++] = v[j];
     34                 if(v[j] == T)   return 1;
     35             }
     36     }
     37     return 0;
     38 }
     39 
     40 int dfs(int cur,int a){
     41     if(cur == T)    return a;
     42     for(int &i = work[cur];i != -1;i = next[i])
     43         if(w[i] && d[v[i]] == d[cur] + 1)
     44             if(int t = dfs(v[i],min(a,w[i]))){
     45                 w[i] -= t;w[i^1] += t;
     46                 return t;
     47             }
     48     return 0;
     49 }
     50 
     51 int dinic(){
     52     int ans = 0;
     53     while(bfs()){
     54         memcpy(work,first,sizeof(first));
     55         while(int t = dfs(S,INF))   ans += t;
     56     }
     57     return ans;
     58 }
     59 
     60 void dfs1(int u){
     61     f1[u] = 1;
     62     for(int i = first[u];i != -1;i = next[i]){
     63         if(!f1[v[i]] && w[i])   dfs1(v[i]);
     64     }
     65 }
     66 
     67 void dfs2(int u){
     68     f2[u] = 1;
     69     for(int i = first[u];i != -1;i = next[i]){
     70         if(!f2[v[i]] && w[i^1]) dfs2(v[i]);
     71     }
     72 }
     73 
     74 int solve(){
     75     memset(f1,0,sizeof(f1));
     76     memset(f2,0,sizeof(f2));
     77     dfs1(S);
     78     dfs2(T);
     79     int ret = 0;
     80     for(int i = 0;i < e;i += 2){
     81         if(f1[u[i]] && f2[v[i]] && !w[i])
     82             ret++;
     83     }
     84     return ret;
     85 }
     86 
     87 int main()
     88 {
     89     init();
     90     int n,m;
     91     scanf("%d%d",&n,&m);
     92     S = 0,T = n-1;
     93     for(int i = 0;i < m;i++){
     94         int a,b,c;
     95         scanf("%d%d%d",&a,&b,&c);
     96         add_edge(a,b,c);
     97     }
     98     dinic();
     99     printf("%d
    ",solve());
    100     return 0;
    101 }
    View Code
  • 相关阅读:
    C语言基础学习8:指针数组
    C语言基础学习7:返回指针值的函数
    C语言基础学习6: 指向函数的指针
    C语言基础学习5:字符串与指针
    C语言基础学习4:数组与指针
    C语言基础学习3:指针
    python 入门 之二 列表 元组 字典 字符串 集合的定义及基本操作
    python入门之路 一
    whl格式 和egg格式
    python 连接mongodb ,并将EXCEL文档导入mongodb
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/3417156.html
Copyright © 2020-2023  润新知