zoukankan      html  css  js  c++  java
  • ZOJ 2532 Internship 网络流求关键边

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2532

    题意:给出一张图,有N个城市,M个中继站,和L条线路连接。

    城市发送数据,最终发送到总部(标号为0),问增大哪些线路带宽能够增加总部接收到的带宽。(考虑一条边的时候,增大这条边,别的不能变化)。

    思路:

    由于时间复杂度,依次把每条边的容量+1,然后求最大流与原来的最大流相比较,这种做法是不可行的。

    考虑最大流算法,是不停地找增广路。

    那么如果一条边u->v,如果从源点开始不停找增广路,能够找到点u。

    从汇点开始反向找增广路,能够找到点v,且u->v满流,那么只要增加这条边的容量,就可以增加最大流,符合题目中的条件。

    由于有多个城市,先设立一个超级源点s,连边到每个城市,容量为正无穷。

    然后把原图中给出的边在图中连接起来,容量即给出的对应值。

    把0号设为汇点。然后求最大流。

    再分别就源点和汇点dfs找出源点增广路能够到达的点from[u] = 1,和汇点增广路能够到达的点to[v] = 1。注意反向找边的时候,判断满流的条件是判断其对应的正向边是否满流。

    检查残量网络中的边,设为u->v,如果这条边满流,且from[u]=1,to[v]=1,则这条边满足条件。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define maxn 110
      4 const int inf = 0x3f3f3f3f;
      5 int N, M, L;
      6 struct Edge
      7 {
      8     int from, to, cap, flow, id;
      9     Edge(int f, int t, int c, int fl, int i)
     10     {
     11         from = f; to = t; cap = c; flow = fl; id = i; 
     12     }
     13 };
     14 int from[maxn], to[maxn];
     15 int n, m, s, t;
     16 vector <Edge> edges;
     17 vector <int> G[maxn];
     18 int vis[maxn], cur[maxn], d[maxn];
     19 void AddEdge(int from, int to, int cap, int id)
     20 {
     21     edges.push_back(Edge(from, to, cap, 0, id));
     22     edges.push_back(Edge(to, from, 0, 0, -1));
     23     m = edges.size();
     24     G[from].push_back(m-2);
     25     G[to].push_back(m-1);
     26 }
     27 bool bfs()
     28 {
     29     memset(vis, 0, sizeof(vis));
     30     vis[s] = 1;
     31     d[s] = 0;
     32     queue <int> q;
     33     q.push(s);
     34     while(!q.empty())
     35     {
     36         int u = q.front(); 
     37         q.pop();
     38         for(int i = 0; i < G[u].size(); i++)
     39         {
     40             Edge &e = edges[G[u][i]];
     41             if(!vis[e.to] && e.cap > e.flow)
     42             {
     43                 vis[e.to] = 1;
     44                 d[e.to] = d[u] + 1;
     45                 q.push(e.to);
     46             }
     47         }
     48     }
     49     return vis[t];
     50 }
     51 int dfs(int x, int a)
     52 {
     53     if(x == t || a == 0) return a;
     54     int flow = 0, f;
     55     for(int &i = cur[x]; i < G[x].size(); i++)
     56     {
     57         Edge &e = edges[G[x][i]];
     58         if(d[x]+1 == d[e.to] && (f = dfs(e.to, min(e.cap-e.flow, a))) > 0)
     59         {
     60             e.flow += f;
     61             edges[G[x][i]^1].flow -= f;
     62             flow += f;
     63             a -= f;
     64             if(a == 0) break;
     65         }
     66     }
     67     return flow;
     68 }
     69 int MaxFlow()
     70 {
     71     int flow = 0;
     72     while(bfs())
     73     {
     74         memset(cur, 0, sizeof(cur));
     75         flow += dfs(s, inf);
     76     }
     77     return flow;
     78 }
     79 void dfsfrom(int fa)
     80 {
     81     from[fa] = 1;
     82     for(int i = 0; i < G[fa].size(); i++)
     83     {
     84         Edge &e = edges[G[fa][i]];
     85         if(e.id == -1) continue;         //反向边
     86         if(from[e.to]) continue;          //已经访问过
     87         if(e.cap == e.flow) continue;   //满流
     88         dfsfrom(e.to);
     89     }
     90 }
     91 void dfsto(int fa)
     92 {
     93     to[fa] = 1;
     94     for(int i = 0; i < G[fa].size(); i++)
     95     {
     96         Edge &e = edges[G[fa][i]];
     97         if(e.id != -1) continue;       //反向边
     98         if(edges[G[fa][i]-1].cap == edges[G[fa][i]-1].flow) continue;  //满流
     99         if(to[e.to]) continue;       //已经访问过
    100         dfsto(e.to);
    101     }
    102 }
    103 int main()
    104 {
    105     while(scanf("%d%d%d", &N,&M,&L) && N)
    106     {
    107         t = 0; s = N+M+1;
    108         edges.clear();
    109         for(int i = 0; i <= N+M+1; i++) G[i].clear();
    110 
    111         for(int i = 1; i <= L; i++)
    112         {
    113             int a, b, c;
    114             scanf("%d%d%d", &a, &b, &c);
    115             AddEdge(a, b, c, i);
    116         }
    117         for(int i = 1; i <= N; i++) AddEdge(s, i, inf, -2);
    118 
    119         int flow = MaxFlow();
    120         memset(from, 0, sizeof(from));
    121         memset(to, 0, sizeof(to));
    122         dfsfrom(s);
    123         dfsto(t);
    124         
    125         bool flag = true;
    126         for(int i = 0; i < 2*L; i += 2)
    127         {
    128             if(edges[i].cap == edges[i].flow 
    129             && from[edges[i].from] && to[edges[i].to])
    130             {
    131                 if(flag){flag = false; printf("%d", edges[i].id);}
    132                 else printf(" %d", edges[i].id);
    133             }
    134         }
    135         printf("
    ");
    136 
    137     }
    138     return 0;
    139 }
  • 相关阅读:
    如何复制图文消息封面图片?正文没显示
    微信企业号已开通账号超过10万 日均消息量超过100万条
    微信服务号模板消息接口新增"设置行业"和"添加模板"及细节优化
    张小龙在微信公开课上的演讲
    做微信营销你知道男女用微信的习惯吗?
    微信时代,"邮"你选择 腾讯企业邮箱推新玩法
    亲身体验,不要再拖! 拖! 拖!
    The Promise of Deep Learning
    判断两个数组是否相等
    matlab学习笔记(一)单元数组
  • 原文地址:https://www.cnblogs.com/titicia/p/4857058.html
Copyright © 2011-2022 走看看