zoukankan      html  css  js  c++  java
  • UVA10480 Sabotage —— 最小割最大流

    题目链接:https://vjudge.net/problem/UVA-10480

    题解:

    实际就是求最小割集。

    1.什么是网络流图的“割”?答:一个边的集合,使得网络流图删除这些边之后,点被分成两部分S和T, 且源点位于S中, 汇点位于T中。注意:不能存在独立于S和T的点。

    2.对于最小割集中的边,它在残余网络中容量为0。

    3.从源点出发,沿着有残余容量的边走,能够访问到的点都属于S集合,否则属于T集合。

    代码如下:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <cmath>
      7 #include <queue>
      8 #include <stack>
      9 #include <map>
     10 #include <string>
     11 #include <set>
     12 using namespace std;
     13 typedef long long LL;
     14 const int INF = 2e9;
     15 const LL LNF = 9e18;
     16 const int mod = 1e9+7;
     17 const int MAXN = 1e2+10;
     18 
     19 int maze[MAXN][MAXN];
     20 int gap[MAXN], dis[MAXN], pre[MAXN], cur[MAXN];
     21 int flow[MAXN][MAXN];
     22 
     23 int sap(int start, int end, int nodenum)
     24 {
     25     memset(cur, 0, sizeof(cur));
     26     memset(dis, 0, sizeof(dis));
     27     memset(gap, 0, sizeof(gap));
     28     memset(flow, 0, sizeof(flow));
     29     int u = pre[start] = start, maxflow = 0, aug = INF;
     30     gap[0] = nodenum;
     31 
     32     while(dis[start]<nodenum)
     33     {
     34         loop:
     35         for(int v = cur[u]; v<nodenum; v++)
     36         if(maze[u][v]-flow[u][v]>0 && dis[u] == dis[v]+1)
     37         {
     38             aug = min(aug, maze[u][v]-flow[u][v]);
     39             pre[v] = u;
     40             u = cur[u] = v;
     41             if(v==end)
     42             {
     43                 maxflow += aug;
     44                 for(u = pre[u]; v!=start; v = u, u = pre[u])
     45                 {
     46                     flow[u][v] += aug;
     47                     flow[v][u] -= aug;
     48                 }
     49                 aug = INF;
     50             }
     51             goto loop;
     52         }
     53 
     54         int mindis = nodenum-1;
     55         for(int v = 0; v<nodenum; v++)
     56             if(maze[u][v]-flow[u][v]>0 && mindis>dis[v])
     57             {
     58                 cur[u] = v;
     59                 mindis = dis[v];
     60             }
     61         if((--gap[dis[u]])==0) break;
     62         gap[dis[u]=mindis+1]++;
     63         u = pre[u];
     64     }
     65     return maxflow;
     66 }
     67 
     68 bool vis[MAXN];
     69 void dfs(int u, int n)
     70 {
     71     vis[u] = true;
     72     for(int v = 0; v<n; v++)
     73         if(maze[u][v]-flow[u][v] && !vis[v])
     74             dfs(v, n);
     75 }
     76 
     77 int edge[MAXN*MAXN][2];
     78 int main()
     79 {
     80     int n, m;
     81     while(scanf("%d%d", &n, &m)&&(n||m))
     82     {
     83         memset(maze, 0, sizeof(maze));
     84         for(int i = 1; i<=m; i++)
     85         {
     86             int u, v, w;
     87             scanf("%d%d%d", &u,&v,&w);
     88             edge[i][0] = --u; edge[i][1] = --v;
     89             maze[u][v] = w;
     90             maze[v][u] = w;
     91         }
     92 
     93         int start = 0, end = 1;
     94         sap(start, end, n);
     95 
     96         memset(vis, false, sizeof(vis));
     97         dfs(0, n);
     98         for(int i = 1; i<=m; i++)
     99         {
    100             int u = edge[i][0];
    101             int v = edge[i][1];
    102             if( (vis[u] && !vis[v]) || (!vis[u] && vis[v]) )
    103                 printf("%d %d
    ", u+1, v+1);
    104         }
    105         printf("
    ");
    106     }
    107 }
    View Code
  • 相关阅读:
    234. Palindrome Linked List(判断链表是否回文)
    141. Linked List Cycle(判断链表是否有环)
    第二届“中国高校计算机大赛-大数据挑战赛” 20名
    Spark集群 Python Package管理
    Android中单选框RadioButton的基本用法
    【Android】进程间通信IPC——Binder
    Spring Boot 集成 JWT 实现单点登录授权
    pythonGUI编程——Qt库(1)
    Android获取SD卡路径/内存的几种方法
    Android主题更换换肤
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8116494.html
Copyright © 2011-2022 走看看