zoukankan      html  css  js  c++  java
  • BZOJ 1797: [Ahoi2009]Mincut 最小割

    1797: [Ahoi2009]Mincut 最小割

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2055  Solved: 879
    [Submit][Status][Discuss]

    Description

    A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路。设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci。现在B国想找出一个路径切断方案,使中转站s不能到达中转站t,并且切断路径的代价之和最小。 小可可一眼就看出,这是一个求最小割的问题。但爱思考的小可可并不局限于此。现在他对每条单向道路提出两个问题: 问题一:是否存在一个最小代价路径切断方案,其中该道路被切断? 问题二:是否对任何一个最小代价路径切断方案,都有该道路被切断? 现在请你回答这两个问题。

    Input

    第一行有4个正整数,依次为N,M,s和t。第2行到第(M+1)行每行3个正 整数v,u,c表示v中转站到u中转站之间有单向道路相连,单向道路的起点是v, 终点是u,切断它的代价是c(1≤c≤100000)。 注意:两个中转站之间可能有多条道路直接相连。 同一行相邻两数之间可能有一个或多个空格。

    Output

    对每条单向边,按输入顺序,依次输出一行,包含两个非0即1的整数,分 别表示对问题一和问题二的回答(其中输出1表示是,输出0表示否)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

    Sample Input

    6 7 1 6
    1 2 3
    1 3 2
    2 4 4
    2 5 1
    3 5 5
    4 6 2
    5 6 3

    Sample Output

    1 0
    1 0
    0 0
    1 0
    0 0
    1 0
    1 0

    HINT

    设第(i+1)行输入的边为i号边,那么{1,2},{6,7},{2,4,6}是仅有的三个最小代价切割方案。它们的并是{1,2,4,6,7},交是 。 【数据规模和约定】 测试数据规模如下表所示 数据编号 N M 数据编号 N M 1 10 50 6 1000 20000 2 20 200 7 1000 40000 3 200 2000 8 2000 50000 4 200 2000 9 3000 60000 5 1000 20000 10 4000 60000



    2015.4.16新加数据一组,可能会卡掉从前可以过的程序。

    Source

    [Submit][Status][Discuss]

    求最小割的必须边和可行边。

    方法是在残量网络上跑Tarjan求出所有的SCC(强连通分量),并对SCC标号。

    如果一条满流边满足u和v不属于同一个SCC,则是一条可行边。

    如果一条满流边满足u和S属于同一个SCC且v和T属于同一个SCC,则是一条必须边。

    所有的必须边一定都是可行边。

      1 #include <bits/stdc++.h>
      2 
      3 #define fread_siz 1024 
      4 
      5 inline int get_c(void)
      6 {
      7     static char buf[fread_siz];
      8     static char *head = buf + fread_siz;
      9     static char *tail = buf + fread_siz;
     10     
     11     if (head == tail)
     12         fread(head = buf, 1, fread_siz, stdin);
     13         
     14     return *head++;
     15 }
     16 
     17 inline int get_i(void)
     18 {
     19     register int ret = 0;
     20     register int neg = false;
     21     register int bit = get_c();
     22     
     23     for (; bit < 48; bit = get_c())
     24         if (bit == '-')neg ^= true;
     25         
     26     for (; bit > 47; bit = get_c())
     27         ret = ret * 10 + bit - 48;
     28         
     29     return neg ? -ret : ret;
     30 }
     31 
     32 template <class T>
     33 inline T min(T a, T b)
     34 {
     35     return a < b ? a : b;
     36 }
     37 
     38 #define inf 2e9
     39 #define maxn 200005
     40 
     41 int n, m;
     42 int s, t;
     43 
     44 int edges;
     45 int hd[maxn];
     46 int nt[maxn];
     47 int to[maxn];
     48 int fl[maxn];
     49 
     50 inline void add_edge(int u, int v, int f)
     51 {
     52     nt[edges] = hd[u]; to[edges] = v; fl[edges] = f; hd[u] = edges++;
     53     nt[edges] = hd[v]; to[edges] = u; fl[edges] = 0; hd[v] = edges++;
     54 }
     55 
     56 int dep[maxn];
     57 
     58 inline bool bfs(void)
     59 {
     60     static int que[maxn];
     61     static int head, tail;
     62     
     63     memset(dep, 0, sizeof(dep));
     64     
     65     head = 0, tail = 0;
     66     que[tail++] = s;
     67     dep[s] = 1;
     68     
     69     while (head != tail)
     70     {
     71         int u = que[head++], v;
     72         
     73         for (int i = hd[u]; ~i; i = nt[i])
     74             if (!dep[v = to[i]] && fl[i])
     75             {
     76                 dep[v] = dep[u] + 1;
     77                 que[tail++] = v;
     78             }
     79     }
     80     
     81     return dep[t];
     82 }
     83 
     84 int dfs(int u, int f)
     85 {
     86     if (u == t || !f)
     87         return f;
     88         
     89     int used = 0, flow, v;
     90     
     91     for (int i = hd[u]; ~i; i = nt[i])
     92         if (dep[v = to[i]] == dep[u] + 1)
     93         {
     94             flow = dfs(v, min(f - used, fl[i]));
     95             
     96             used += flow;
     97             fl[i] -= flow;
     98             fl[i^1] += flow;
     99             
    100             if (used == f)
    101                 return f;
    102         }
    103         
    104     if (!used)
    105         dep[u] = 0;
    106         
    107     return used;
    108 }
    109 
    110 inline bool dfs(void)
    111 {
    112     return dfs(s, inf) != 0;
    113 }
    114 
    115 inline void max_flow(void)
    116 {
    117     while (bfs())
    118     while (dfs());
    119 }
    120 
    121 int dfn[maxn];
    122 int scc[maxn];
    123 
    124 void tarjan(int u)
    125 {
    126     static int tim = 0;
    127     static int cnt = 0;
    128     static int top = 0;
    129     static int low[maxn];
    130     static int stk[maxn];
    131     
    132     dfn[stk[++top] = u] = low[u] = ++tim;
    133     
    134     for (int i = hd[u], v; ~i; i = nt[i])if (fl[i])
    135     {
    136         if (!dfn[v = to[i]])
    137             tarjan(v), low[u] = min(low[u], low[v]);
    138         else if (!scc[v])
    139             low[u] = min(low[u], dfn[v]);
    140     }
    141     
    142     if (low[u] == dfn[u])
    143     {
    144         ++cnt; int p;
    145         do
    146             scc[p = stk[top--]] = cnt;
    147         while (p != u);
    148     }
    149 }
    150 
    151 signed main(void)
    152 {
    153     n = get_i();
    154     m = get_i();
    155     s = get_i();
    156     t = get_i();
    157     
    158     memset(hd, -1, sizeof(hd));
    159     
    160     for (int i = 1; i <= m; ++i)
    161     {
    162         int u = get_i();
    163         int v = get_i();
    164         int w = get_i();
    165         add_edge(u, v, w);
    166     }
    167     
    168     max_flow(); 
    169     
    170     for (int i = 1; i <= n; ++i)
    171         if (!dfn[i])tarjan(i);
    172         
    173     for (int i = 0; i < edges; i += 2)
    174     {
    175         int u = to[i ^ 1], v = to[i];
    176         if (fl[i] || scc[u] == scc[v])
    177             puts("0 0");
    178         else if (scc[u] == scc[s] && scc[v] == scc[t])
    179             puts("1 1");
    180         else
    181             puts("1 0");
    182     }
    183 }

    @Author: YouSiki

  • 相关阅读:
    LeetCode 1275. 找出井字棋的获胜者 Find Winner on a Tic Tac Toe Game
    LeetCode 307. 区域和检索
    LeetCode 1271 十六进制魔术数字 Hexspeak
    秋实大哥与花 线段树模板
    AcWing 835. Trie字符串统计
    Leetcode 216. 组合总和 III
    Mybatis 示例之 复杂(complex)属性(property)
    Mybatis 示例之 复杂(complex)属性(property)
    Mybatis 高级结果映射 ResultMap Association Collection
    Mybatis 高级结果映射 ResultMap Association Collection
  • 原文地址:https://www.cnblogs.com/yousiki/p/6221446.html
Copyright © 2011-2022 走看看