zoukankan      html  css  js  c++  java
  • 2017 01 05 校内网络流小测

    鉴于这几日大家都有学习网络流知识,LincHpin大爷决定考一考我们网络流,然后,我就爆零了,233……

    T1 Seal

    想了好久,也不知道怎么建图,然后心态就崩了,就刷BZOJ去了……

    考场上写的随机化和错误贪心都被大爷卡了,T_T,Orz YYH,YZY,GZZ三位AK大佬。

    首先,以一个恶魔为中心,形成一个直角的充要条件是,在左右相邻格子中选一个,在上下相邻格子中选一个。

    然后发现,对于那些水晶格,同为奇数行的总是不会同时被选,同为偶数行的也不会同时被选(此指被选中流向同一个恶魔格子)。就是说,水晶格可以按照所在行(或者列,随便啦)的奇偶进行黑白染色,每个恶魔总是需要匹配一个黑水晶和一个白水晶。

    所以把黑水晶放在左侧,每个和源点之间有容量为1的边;白水晶放在右侧,每个和汇点之间也有容量为1的边。中间是恶魔点,每个恶魔拆成两个点,分别和相邻的黑、白水晶相连,中间是容量为1的边。跑最大流就行了。

      1 #include <cstdio>
      2 
      3 inline int nextChar(void) {
      4     const int siz = 1024;
      5     
      6     static char buf[siz];
      7     static char *hd = buf + siz;
      8     static char *tl = buf + siz;
      9     
     10     if (hd == tl)
     11         fread(hd = buf, 1, siz, stdin);
     12         
     13     return *hd++;
     14 }
     15  
     16 inline int nextInt(void) {
     17     register int ret = 0;
     18     register int neg = false;
     19     register int bit = nextChar();
     20     
     21     for (; bit < 48; bit = nextChar())
     22         if (bit == '-')neg ^= true;
     23         
     24     for (; bit > 47; bit = nextChar())
     25         ret = ret * 10 + bit - 48;
     26         
     27     return neg ? -ret : ret;
     28 }
     29 
     30 int n, m;
     31 
     32 bool g[55][55];
     33 
     34 inline bool next(void)
     35 {
     36     char c = nextChar();
     37     
     38     while (c != '.' && c != 'X')
     39         c = nextChar();
     40         
     41     return c == '.';
     42 }
     43 
     44 const int siz = 500005;
     45 const int inf = 1000000007;
     46 
     47 int tot;
     48 int s, t;
     49 int hd[siz];
     50 int to[siz];
     51 int fl[siz];
     52 int nt[siz];
     53 
     54 inline void add(int u, int v, int f)
     55 {
     56     nt[tot] = hd[u]; to[tot] = v; fl[tot] = f; hd[u] = tot++;
     57     nt[tot] = hd[v]; to[tot] = u; fl[tot] = 0; hd[v] = tot++;
     58 }
     59 
     60 int dep[siz];
     61 
     62 inline bool bfs(void)
     63 {
     64     static int que[siz], head, tail;
     65     
     66     for (int i = s; i <= t; ++i)dep[i] = 0;
     67     
     68     dep[que[head = 0] = s] = tail = 1;
     69     
     70     while (head != tail)
     71     {
     72         int u = que[head++], v;
     73         
     74         for (int i = hd[u]; ~i; i = nt[i])
     75             if (!dep[v = to[i]] && fl[i])
     76                 dep[que[tail++] = v] = dep[u] + 1;
     77     }
     78     
     79     return dep[t];
     80 }
     81 
     82 int cur[siz];
     83 
     84 inline int min(int a, int b)
     85 {
     86     return a < b ? a : b;
     87 }
     88 
     89 int dfs(int u, int f)
     90 {
     91     if (u == t || !f)
     92         return f;
     93         
     94     int used = 0, flow, v;
     95     
     96     for (int i = cur[u]; ~i; i = nt[i])
     97         if (dep[v = to[i]] == dep[u] + 1 && fl[i])
     98         {
     99             flow = dfs(v, min(fl[i], f - used));
    100             
    101             used += flow;
    102             fl[i] -= flow;
    103             fl[i^1] += flow;
    104             
    105             if (used == f)
    106                 return f;
    107             
    108             if (fl[i])
    109                 cur[u] = i;
    110         }
    111         
    112     if (!used)
    113         dep[u] = 0;
    114     
    115     return used;
    116 }
    117 
    118 inline int maxFlow(void)
    119 {
    120     int maxFlow = 0, newFlow;
    121     
    122     while (bfs())
    123     {
    124         for (int i = s; i <= t; ++i)
    125             cur[i] = hd[i];
    126             
    127         while (newFlow = dfs(s, inf))
    128             maxFlow += newFlow;
    129     }
    130     
    131     return maxFlow;
    132 }
    133 
    134 inline int pos(int x, int y)
    135 {
    136     return m * (x - 1) + y;
    137 }
    138 
    139 const int mv[4][2] = 
    140 {
    141     {0, +1},
    142     {0, -1},
    143     {-1, 0},
    144     {+1, 0}
    145 };
    146 
    147 signed main(void)
    148 {
    149     freopen("Seal.in", "r", stdin);
    150     freopen("Seal.out", "w", stdout);
    151     
    152     n = nextInt();
    153     m = nextInt();
    154     
    155     
    156     for (int i = 1; i <= n; ++i)
    157         for (int j = 1; j <= m; ++j)
    158             g[i][j] = next();
    159             
    160     s = 0, t = n * m * 2 + 1;
    161             
    162     for (int i = s; i <= t; ++i)
    163         hd[i] = -1;
    164     
    165     for (int i = 1; i <= n; ++i)
    166         for (int j = 1; j <= m; ++j)
    167             if (g[i][j])
    168             {
    169                 if ((i + j) & 1)
    170                 {
    171                     if (i & 1)
    172                         add(s, pos(i, j), 1);
    173                     else
    174                         add(pos(i, j), t, 1);
    175                 }
    176                 else
    177                 {
    178                     for (int k = 0; k < 4; ++k)
    179                     {
    180                         int x = i + mv[k][0];
    181                         int y = j + mv[k][1];
    182                         
    183                         if (x < 1 || x > n)
    184                             continue;
    185                         if (y < 1 || y > m)
    186                             continue;
    187                         if (!g[x][y])
    188                             continue;
    189                             
    190                         if (x & 1)
    191                             add(pos(x, y), pos(i, j), 1);
    192                         else
    193                             add(pos(i, j) + n*m, pos(x, y), 1);
    194                             
    195                         add(pos(i, j), pos(i, j) + n*m, 1);
    196                     }
    197                 }
    198             }
    199             
    200     printf("%d
    ", maxFlow());
    201             
    202     return fclose(stdin), fclose(stdout), 0;
    203 }

    T2 Repair

     依旧不会做,然后听LH大爷讲题解,讲完就怀疑自己智商了……

    有点像是可行流问题(本来就是可行流好嘛),只是需要分类讨论一下。

    对于一条边,如果一开始流量$F$大于$C$,即$F gt C$,那么有如下情况:

    如果最后流量$X$大于$F$,即$X gt F gt C$,那么有$fare=X-F+X-C$,如果设$K=F-C$,有$fare=K+2(X-F)$.

    如果最后流量$X$在$F$和$C$之间,即$F gt X gt C$,那么有$fare=F-X+X-C=K$.

    如果最后流量$X$小于$C$,即$F gt C gt X$,那么有$fare=F-X=K+C-X$.

    不难总结出对于这类边的建新边方式:

    先将$K$直接统计到答案之中,然后从$u$向$v$连容量为$INF$的边,费用为$2$,从$v$向$u$连容量为$F-C$的边,费用为$0$,从$v$向$u$连容量为$C$的边,费用为$1$。

    对于一条边,如果一开始流量$F$小于$C$,即$F lt C$,那么有如下情况:

    如果最后流量$X$大于$C$,即$X gt C gt F$,那么有$fare=X-C+X-F$。

    如果最后流量$X$在$C$和$F$之间,即$C gt X gt F$,那么有$fare=X-F$。

    如果最后流量$X$小于$F$,即$C gt F gt X$,那么有$fare=F-X$。

    不难总结出对这类边的建新边方式:

    从$u$向$v$连容量为$C-F$的边,费用为$1$,从$u$向$v$连容量为$INF$的边,费用为$2$,从$v$向$u$连容量为$F$的边,费用为$1$。

    最后为了满足流量守恒,设立新的源汇点,源点向流入量多的点连边,流出量多的点向汇点连边,原汇点向原源点连无穷的边,跑最小费用最大流即可。

      1 #include <cstdio>
      2 
      3 inline int nextChar(void) {
      4     const int siz = 1024;
      5     
      6     static char buf[siz];
      7     static char *hd = buf + siz;
      8     static char *tl = buf + siz;
      9     
     10     if (hd == tl)
     11         fread(hd = buf, 1, siz, stdin);
     12         
     13     return *hd++;
     14 }
     15  
     16 inline int nextInt(void) {
     17     register int ret = 0;
     18     register int neg = false;
     19     register int bit = nextChar();
     20     
     21     for (; bit < 48; bit = nextChar())
     22         if (bit == '-')neg ^= true;
     23         
     24     for (; bit > 47; bit = nextChar())
     25         ret = ret * 10 + bit - 48;
     26         
     27     return neg ? -ret : ret;
     28 }
     29 
     30 const int siz = 5000005;
     31 const int inf = 1000000007;
     32 
     33 int n, m;
     34 int answer;
     35 int del[siz];
     36 
     37 int tot;
     38 int s, t;
     39 int hd[siz];
     40 int to[siz];
     41 int fl[siz];
     42 int vl[siz];
     43 int nt[siz];
     44 
     45 inline void add(int u, int v, int f, int w)
     46 {
     47 //    printf("add %d %d %d %d
    ", u, v, f, w);
     48     nt[tot] = hd[u]; to[tot] = v; fl[tot] = f; vl[tot] = +w; hd[u] = tot++;
     49     nt[tot] = hd[v]; to[tot] = u; fl[tot] = 0; vl[tot] = -w; hd[v] = tot++;
     50 }
     51 
     52 int dep[siz];
     53 
     54 inline bool bfs(void)
     55 {
     56     static int que[siz], head, tail;
     57     
     58     for (int i = s; i <= t; ++i)dep[i] = 0;
     59     
     60     dep[que[head = 0] = s] = tail = 1;
     61     
     62     while (head != tail)
     63     {
     64         int u = que[head++], v;
     65         
     66         for (int i = hd[u]; ~i; i = nt[i])
     67             if (!dep[v = to[i]] && fl[i] && !vl[i])
     68                 dep[que[tail++] = v] = dep[u] + 1;
     69     }
     70     
     71     return dep[t];
     72 }
     73 
     74 int cur[siz];
     75 
     76 inline int min(int a, int b)
     77 {
     78     return a < b ? a : b;
     79 }
     80 
     81 int dfs(int u, int f)
     82 {
     83     if (u == t || !f)
     84         return f;
     85         
     86     int used = 0, flow, v;
     87     
     88     for (int i = hd[u]; ~i; i = nt[i])
     89         if (dep[v = to[i]] == dep[u] + 1 && fl[i] && !vl[i])
     90         {
     91             flow = dfs(v, min(fl[i], f - used));
     92             
     93             used += flow;
     94             fl[i] -= flow;
     95             fl[i^1] += flow;
     96             
     97             if (used == f)
     98                 return f;
     99                 
    100             if (fl[i])
    101                 cur[u] = i;
    102         }
    103         
    104     if (!used)
    105         dep[u] = 0;
    106     
    107     return used;
    108 }
    109 
    110 inline void maxFlow(void)
    111 {
    112     while (bfs())
    113         while (dfs(s, inf));
    114 }
    115 
    116 int dis[siz];
    117 int pre[siz];
    118 
    119 inline bool spfa(void)
    120 {
    121     static int que[siz];
    122     static int inq[siz];
    123     static int head, tail;
    124     
    125     for (int i = s; i <= t; ++i)
    126         inq[i] = 0, dis[i] = inf;
    127         
    128     head = 0, tail = 0;
    129     que[tail++] = s;
    130     pre[s] = -1;
    131     dis[s] = 0;
    132     
    133     while (head != tail)
    134     {
    135         int u = que[head++], v; inq[u] = 0;
    136         
    137         for (int i = hd[u]; ~i; i = nt[i])
    138             if (dis[v = to[i]] > dis[u] + vl[i] && fl[i])
    139             {
    140                 dis[v] = dis[u] + vl[i], pre[v] = i ^ 1;
    141                 if (!inq[v])
    142                     inq[que[tail++] = v] = 1;
    143             }
    144     }
    145     
    146     return dis[t] < inf;
    147 }
    148 
    149 inline void minCost(void)
    150 {
    151     while (spfa())
    152     {
    153         int flow = inf;
    154         
    155         for (int i = pre[t]; ~i; i = pre[to[i]])
    156             if (fl[i ^ 1] < flow)flow = fl[i ^ 1];
    157             
    158         for (int i = pre[t]; ~i; i = pre[to[i]])
    159             fl[i] += flow, fl[i ^ 1] -= flow;
    160             
    161         answer += dis[t] * flow;
    162     }
    163 }
    164 
    165 signed main(void)
    166 {
    167     freopen("Repair.in", "r", stdin);
    168     freopen("Repair.out", "w", stdout);
    169     
    170     n = nextInt();
    171     m = nextInt();
    172     
    173     s = 0, t = n + 1;
    174     
    175     for (int i = s; i <= t; ++i)
    176         hd[i] = -1;
    177     
    178     for (int i = 1; i <= m; ++i)
    179     {
    180         int u = nextInt();
    181         int v = nextInt();
    182         int c = nextInt();
    183         int f = nextInt();
    184         
    185         del[u] += f;
    186         del[v] -= f;
    187         
    188         if (f <= c)
    189         {
    190             add(u, v, c - f, 1);
    191             add(u, v, inf, 2);
    192             add(v, u, f, 1);
    193         }
    194         else
    195         {
    196             answer += f - c;
    197             add(u, v, inf, 2);
    198             add(v, u, f - c, 0);
    199             add(v, u, c, 1);
    200         }
    201     }
    202     
    203     add(n, 1, inf, 0);
    204     
    205     for (int i = 1; i <= n; ++i)
    206         if (del[i] < 0)
    207             add(s, i, -del[i], 0);
    208         else if (del[i] > 0)
    209             add(i, t, del[i], 0);
    210             
    211     maxFlow();
    212     
    213     minCost();
    214     
    215     printf("%d
    ", answer);
    216     
    217     return fclose(stdin), fclose(stdout), 0;
    218 }

    T3 Flow

    依旧不会,看到$G(f)$函数就是mengbi的。

    GZZ神犇说,MCMF中每次增广出来的路径,就是$C(f)$关于$F(f)$函数中的一段一次函数…… $OTZ GZZ$

    然后,分步跑出来每一段的函数,求函数上距离(maxFlow,0)点的最近距离即可,我怎么这么蠢,23333

      1 #include <cstdio>
      2 
      3 template <class T>
      4 inline T min(T a, T b)
      5 {
      6     return a < b ? a : b;
      7 }
      8 
      9 template <class T>
     10 T gcd(T a, T b)
     11 {
     12     return b ? gcd(b, a % b) : a;
     13 }
     14 
     15 template <class T>
     16 inline T sqr(T x)
     17 {
     18     return x * x;
     19 }
     20 
     21 #define int long long
     22 
     23 inline int nextChar(void) {
     24     const int siz = 1024;
     25     
     26     static char buf[siz];
     27     static char *hd = buf + siz;
     28     static char *tl = buf + siz;
     29     
     30     if (hd == tl)
     31         fread(hd = buf, 1, siz, stdin);
     32         
     33     return *hd++;
     34 }
     35  
     36 inline int nextInt(void) {
     37     register int ret = 0;
     38     register int neg = false;
     39     register int bit = nextChar();
     40     
     41     for (; bit < 48; bit = nextChar())
     42         if (bit == '-')neg ^= true;
     43         
     44     for (; bit > 47; bit = nextChar())
     45         ret = ret * 10 + bit - 48;
     46         
     47     return neg ? -ret : ret;
     48 }
     49 
     50 const int siz = 500005;
     51 const int inf = 1000000007;
     52 
     53 int n, m;
     54 
     55 int tot;
     56 int s, t;
     57 int hd[siz];
     58 int nt[siz];
     59 int fl[siz];
     60 int vl[siz];
     61 int to[siz];
     62 
     63 inline void add(int u, int v, int f, int w)
     64 {
     65     nt[tot] = hd[u]; to[tot] = v; vl[tot] = +w; fl[tot] = f; hd[u] = tot++;
     66     nt[tot] = hd[v]; to[tot] = u; vl[tot] = -w; fl[tot] = 0; hd[v] = tot++;
     67 }
     68 
     69 int dep[siz];
     70 
     71 inline bool bfs(void)
     72 {
     73     static int que[siz], head, tail;
     74     
     75     for (int i = 1; i <= n; ++i)dep[i] = 0;
     76     
     77     dep[que[head = 0] = s] = tail = 1;
     78     
     79     while (head != tail)
     80     {
     81         int u = que[head++], v;
     82         
     83         for (int i = hd[u]; ~i; i = nt[i])
     84             if (!dep[v = to[i]] && fl[i])
     85                 dep[que[tail++] = v] = dep[u] + 1;
     86     }
     87     
     88     return dep[t];
     89 }
     90 
     91 int cur[siz];
     92 
     93 int dfs(int u, int f)
     94 {
     95     if (u == t || !f)
     96         return f;
     97         
     98     int used = 0, flow, v;
     99     
    100     for (int i = cur[u]; ~i; i = nt[i])
    101         if (dep[v = to[i]] == dep[u] + 1 && fl[i])
    102         {
    103             flow = dfs(v, min(fl[i], f - used));
    104             
    105             used += flow;
    106             fl[i] -= flow;
    107             fl[i^1] += flow;
    108             
    109             if (used == f)
    110                 return f;
    111             
    112             if (fl[i])
    113                 cur[u] = i;
    114         }
    115         
    116     if (!used)
    117         dep[u] = 0;
    118     
    119     return used;
    120 }
    121 
    122 inline int Dinic(void)
    123 {
    124     int maxFlow = 0, newFlow;
    125     
    126     while (bfs())
    127     {
    128         for (int i = 1; i <= n; ++i)
    129             cur[i] = hd[i];
    130             
    131         while (newFlow = dfs(s, inf))
    132             maxFlow += newFlow;
    133     }
    134     
    135     return maxFlow;
    136 }
    137 
    138 int dis[siz];
    139 int pre[siz];
    140 
    141 inline bool spfa(void)
    142 {
    143     static int que[siz];
    144     static int inq[siz];
    145     static int head, tail;
    146     
    147     for (int i = 1; i <= n; ++i)
    148         dis[i] = inf, inq[i] = 0;
    149         
    150     head = 0, tail = 0;
    151     que[tail++] = s;
    152     pre[s] = -1;
    153     dis[s] = 0;
    154     inq[s] = 1;
    155     
    156     while (head != tail)
    157     {
    158         int u = que[head++], v; inq[u] = 0;
    159         
    160         for (int i = hd[u]; ~i; i = nt[i])
    161             if (fl[i] && dis[v = to[i]] > dis[u] + vl[i])
    162             {
    163                 dis[v] = dis[u] + vl[i], pre[v] = i ^ 1;
    164                 if (!inq[v])inq[que[tail++] = v] = 1;
    165             }
    166     }
    167     
    168     return dis[t] < inf;
    169 }
    170 
    171 signed main(void)
    172 {
    173     freopen("Flow.in", "r", stdin);
    174     freopen("Flow.out", "w", stdout);
    175     
    176     n = nextInt();
    177     m = nextInt();
    178     s = nextInt();
    179     t = nextInt();
    180     
    181     for (int i = 1; i <= n; ++i)
    182         hd[i] = -1;
    183         
    184     for (int i = 1; i <= m; ++i)
    185     {
    186         int x = nextInt();
    187         int y = nextInt();
    188         int u = nextInt();
    189         int c = nextInt();
    190         add(x, y, u, c);
    191     }
    192     
    193     int maxFlow = Dinic();
    194     
    195     for (int i = 0; i < tot; i += 2)
    196         fl[i] += fl[i ^ 1], fl[i ^ 1] = 0;
    197     
    198     int C = 0, F = maxFlow;
    199     
    200     while (spfa())
    201     {
    202         int w = dis[t];
    203         
    204         int flow = inf;
    205         
    206         for (int i = pre[t]; ~i; i = pre[to[i]])
    207             if (fl[i ^ 1] < flow)
    208                 flow = fl[i ^ 1];
    209                 
    210         if (F - w * C >= flow * (sqr(w) + 1)) 
    211         {
    212             for (int i = pre[t]; ~i; i = pre[to[i]])
    213                 fl[i] += flow, fl[i ^ 1] -= flow;
    214                 
    215             F -= flow, C += flow * dis[t];
    216         }
    217         else
    218         {
    219             if (F > w * C)
    220             {
    221                 int r = sqr(w * F + C);
    222                 int d = sqr(w) + 1;
    223                 int g = gcd(r, d);
    224                 printf("%lld/%lld
    ", r / g, d / g);
    225             }
    226             else
    227                 printf("%lld/%lld
    ", sqr(C) + sqr(F), 1LL);
    228             
    229             goto end;
    230         }
    231     }
    232     
    233     printf("%lld/%lld
    ", sqr(C) + sqr(F), 1LL);
    234     
    235 end:return fclose(stdin), fclose(stdout), 0;
    236 }

    @Author: YouSiki

  • 相关阅读:
    数据安全:1.98亿购车者的购车记录公之于众
    【作者面对面问答】包邮送《Redis 5设计与源码分析》5本
    关于区块链学习资料
    《机器学习》周志华西瓜书学习笔记(九):聚类
    Bulletproof零知识证明
    数据接收合并
    数据接收合并
    数据接收合并
    数据接收合并
    Tomcat 8 Host-Manager配置访问的方法,全网唯一正确配置
  • 原文地址:https://www.cnblogs.com/yousiki/p/6253101.html
Copyright © 2011-2022 走看看