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

  • 相关阅读:
    linux常用命令
    chattr无法删除某个文件
    centos如何卸载软件
    linux命令行下的ftp 多文件下载和目录下载
    yum -y upgrade 和 yum -y update 区别
    Pureftpd
    centos rar安装
    linux系统数据盘挂载教程
    anyexec
    _variant_t
  • 原文地址:https://www.cnblogs.com/yousiki/p/6221446.html
Copyright © 2011-2022 走看看