zoukankan      html  css  js  c++  java
  • [AHOI2009]最小割 最小割可行边&必须边

    ~~~题面~~~

    题解:

    做这题的时候才知道有最小割可行边和必须边这种东西。。。。。

    1,最小割可行边,

    意思就是最小割中可能出现的边。

    充要条件:

      1,满流

      2,在残余网络中找不到x ---> y的路径

    解释:

    如果在残余网络中还找得到x ---> y的路径的话,要割掉这条边就还需要割掉另一条路径,这显然是不够优的。

    如果是满流的话显然不是割掉了这条边

    2,最小割必须边

      1,满流

      2,在残余网络中s 可以到 x, y 可以到 t。

    解释:

    满流的原因和上面原因,同时必须边肯定也是可行边(显然可行边的范围就要大一些嘛)。

    如果满流但s不能到x or y 不能到 t,因为这样的话说明在s 到 x(y 到 t)的路上就已经被割掉了,而不是在这里割的。

    但是因为满流了,所以这是可行的,但是由于割在别的地方,说明不是必须的。

    因此s 必须可以到 x, y 必须可以到s才能保证是必须边,而不是可行边 

    至于实现方法就比较妙了。

    如果两个点在一个scc中则表示可以到。

    因此可行边需要保证x和y不在一个scc中。

    而必须边则还需要额外保证s 和 x 属于一个scc, y 和 t属于一个scc

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define R register int
      4 #define getchar() *o++
      5 #define inf 2139062143
      6 #define AC 5000
      7 #define ac 150000
      8 #define D printf("line in %d
    ", __LINE__);
      9 char READ[7000100], *o = READ;
     10 int n, m, s, t, ans, x, cnt, addflow;
     11 int last[AC], c[AC], have[AC], good[AC];
     12 int date[ac], Next[ac], belong[ac], haveflow[ac], Head[AC], tot = 1;//前向星
     13 int low[AC], dfn[AC], scc[AC], timer;//tarjan
     14 int q[AC], head, tail;//队列
     15 int Stack[AC], top;
     16 bool z[AC];//用于tarjan
     17 
     18 inline int read()
     19 {
     20     int x = 0; char c = getchar();
     21     while(c > '9' || c < '0') c = getchar();
     22     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
     23     return x; 
     24 }
     25 
     26 inline void upmin(int &a, int b)
     27 {
     28     if(a > b) a = b;
     29 }
     30 
     31 inline void add(int f, int w, int S)
     32 {
     33     date[++tot] = w, Next[tot] = Head[f], Head[f] = tot, haveflow[tot] = S, belong[tot] = f;
     34     date[++tot] = f, Next[tot] = Head[w], Head[w] = tot;
     35 }
     36 
     37 void pre()
     38 {
     39     int u, v, e;
     40     n = read(), m = read(), s = read(), t = read();
     41     for(R i = 1; i <= m; i++)
     42     {
     43         u = read(), v = read(), e = read();
     44         add(u, v, e);
     45     }
     46 }
     47 
     48 void bfs()
     49 {
     50     int x, now;
     51     c[t] = 1, have[1] = 1, q[++tail] = t;
     52     while(head < tail)
     53     {
     54         x = q[++head]; 
     55         for(R i = Head[x]; i ; i = Next[i])
     56         {
     57             now = date[i];
     58             if(haveflow[i ^ 1] && !c[now])
     59             {
     60                 c[now] = c[x] + 1;
     61                 ++have[c[now]];
     62                 q[++tail] = now;
     63             }
     64         }
     65     }
     66     memcpy(good, Head, sizeof(good));
     67 }
     68 
     69 void aru()
     70 {
     71     while(x != s)
     72     {
     73         haveflow[last[x]] -= addflow;
     74         haveflow[last[x] ^ 1] += addflow;
     75         x = date[last[x] ^ 1];
     76     }
     77     ans += addflow;
     78 }
     79 
     80 void isap()
     81 {
     82     int now; bool done;
     83     x = s, addflow = inf;
     84     while(c[s] != 4801)
     85     {
     86         if(x == t) aru(), addflow = inf;
     87         done = false;
     88         for(R i = good[x]; i ; i = Next[i])
     89         {
     90             now = date[i];
     91             if(haveflow[i] && c[now] == c[x] - 1)
     92             {
     93                 done = true;
     94                 upmin(addflow, haveflow[i]);
     95                 good[x] = last[now] = i;
     96                 x = now;
     97                 break;
     98             }
     99         }
    100         if(!done)
    101         {
    102             int go = 4800;
    103             for(R i = Head[x]; i ; i = Next[i])
    104             {
    105                 now = date[i];
    106                 if(haveflow[i] && c[now]) upmin(go, c[now]);
    107             }
    108             good[x] = Head[x];//error!!!不要忘了重置
    109             if(!(--have[c[x]])) break;
    110             ++have[c[x] = go + 1];
    111             if(x != s) x = date[last[x] ^ 1];
    112         }
    113     }
    114 }
    115 
    116 void tarjan(int x)
    117 {
    118     int now;
    119     dfn[x] = low[x] = ++timer;
    120     z[x] = true;
    121     Stack[++top] = x;
    122     for(R i = Head[x]; i ; i = Next[i])
    123     {
    124         if(!haveflow[i]) continue;//流满表示不联通
    125         now = date[i];
    126         if(!dfn[now]) 
    127         {
    128             tarjan(now);
    129             upmin(low[x], low[now]);
    130         }
    131         else if(z[now]) upmin(low[x], low[now]);
    132     }
    133     if(dfn[x] == low[x])
    134     {
    135         ++cnt;
    136         while(Stack[top] != x)
    137         {
    138             now = Stack[top--];
    139             scc[now] = cnt;
    140             z[now] = false;
    141         }
    142         now = Stack[top--];
    143         scc[now] = cnt;
    144         z[now] = false;
    145     }
    146 }
    147 
    148 void work()
    149 {
    150     int x, y;
    151     for(R i = 2; i <= tot; i += 2)
    152     {
    153         x = belong[i], y = date[i];
    154     //    printf("%d %d
    ", x, y);
    155         if(!haveflow[i] && scc[x] != scc[y])
    156         {
    157             printf("1 ");
    158             if(scc[x] == scc[s] && scc[y] == scc[t]) printf("1
    ");
    159             else printf("0
    ");
    160         }
    161         else printf("0 0
    ");
    162     }
    163 }
    164 
    165 int main()
    166 {
    167 //    freopen("in.in", "r", stdin);
    168     fread(READ, 1, 7000000, stdin);
    169     pre();
    170     bfs();
    171     isap();
    172     for(R i=1;i<=n;i++) 
    173         if(!dfn[i]) tarjan(i);
    174 //    for(R i=1;i<=n;i++) printf("%d ", scc[i]);
    175 //    printf("
    ");
    176 //    for(R i=2;i<=tot;i++) printf("%d ", haveflow[i]);
    177     work();
    178 //    fclose(stdin);
    179     return 0;
    180 }
  • 相关阅读:
    STM32 USB应用——VCP
    基础数据类型与字节数组相互转换 BitConvter类
    C# 16进制与字符串、字节数组之间的转换
    C语言函数手册学习
    C串口通信
    C#串口通信
    C Socket通信编程
    C SOCKET编程
    C# SOCKE通信
    socket阻塞与非阻塞,同步与异步、I/O模型
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9236331.html
Copyright © 2011-2022 走看看