• loj #117. 有源汇有上下界最小流


    题目链接

    有源汇有上下界最小流,->上下界网络流

    注意细节,边数组也要算上后加到SS,TT边。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 
     7 using namespace std;
     8 
     9 const int N = 150010;
    10 const int INF = 1e9;
    11 
    12 struct Edge{
    13     int to,nxt,c;
    14 }e[500100];
    15 int head[N],dis[N],cur[N],M[N];
    16 int q[500100],L,R;
    17 int tot = 1,n,m,S,T,Sum;
    18 
    19 inline char nc() {
    20     static char buf[100000],*p1 = buf,*p2 = buf;
    21     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    22 }
    23 inline int read() {
    24     int x = 0,f = 1;char ch = nc();
    25     for (; ch<'0'||ch>'9';ch=nc()) if(ch=='-') f=-1;
    26     for (; ch>='0'&&ch<='9'; ch=nc()) x=x*10+ch-'0';
    27     return x * f;
    28 }
    29 void add_edge(int u,int v,int c) {
    30     e[++tot].to = v,e[tot].c = c,e[tot].nxt = head[u],head[u] = tot;
    31 }
    32 bool bfs() {
    33     for (int i=1; i<=n+2; ++i) 
    34         cur[i] = head[i],dis[i] = -1;
    35     L = 1,R = 0;
    36     q[++R] = S;
    37     dis[S] = 0;
    38     while (L <= R) {
    39         int u = q[L++];
    40         for (int i=head[u]; i; i=e[i].nxt) {
    41             int v = e[i].to;
    42             if (dis[v] == -1 && e[i].c > 0) {
    43                 dis[v] = dis[u] + 1;
    44                 q[++R] = v;
    45                 if (v == T) return true;
    46             }
    47         }
    48     }
    49     return false;
    50 }
    51 int dfs(int u,int flow) {
    52     if (u == T) return flow;
    53     int used = 0;
    54     for (int &i=cur[u]; i; i=e[i].nxt) {
    55         int v = e[i].to;
    56         if (dis[v] == dis[u] + 1 && e[i].c > 0) {
    57             int tmp = dfs(v,min(e[i].c,flow-used));
    58             if (tmp > 0) {
    59                 e[i].c -= tmp;e[i^1].c += tmp;
    60                 used += tmp;
    61                 if (used == flow) break;
    62             }
    63         }
    64     }
    65     if (used != flow) dis[u] = -1;
    66     return used;
    67 }
    68 int dinic(int s,int t) {
    69     S = s,T = t;
    70     int ans = 0;
    71     while (bfs()) ans += dfs(S,INF);
    72     return ans;
    73 }    
    74 int main () {
    75     n = read(),m = read();
    76     int s = read(),t = read();
    77     int ss = n + 1,tt = n + 2;
    78     for (int i=1; i<=m; ++i) {
    79         int u = read(),v = read(),b = read(),c = read();
    80         add_edge(u,v,c-b);
    81         add_edge(v,u,0);
    82         M[u] -= b;M[v] += b;
    83     }
    84     for (int i=1; i<=n; ++i) {
    85         if (M[i] > 0) add_edge(ss,i,M[i]),add_edge(i,ss,0),Sum += M[i];
    86         if (M[i] < 0) add_edge(i,tt,-M[i]),add_edge(tt,i,0);
    87     }
    88     add_edge(t,s,INF); //-
    89     add_edge(s,t,0);
    90     if (dinic(ss,tt) != Sum) {
    91         printf("please go home to sleep");
    92         return 0;
    93     }
    94     int ans = e[tot].c;
    95     e[tot].c = 0;e[tot ^ 1].c = 0;
    96     ans -= dinic(t,s);
    97     printf("%d",ans);
    98     return 0;
    99 }
  • 相关阅读:
    Gym
    Gym 100712H
    CodeForces
    CodeForces
    P1103 书本整理(DP)
    P1435 回文子串(最长公共子序列)
    P1095 守望者的逃离(线性DP)
    P1077 摆花(背包)
    P1832 A+B Problem(再升级)
    P1757 通天之分组背包(分组背包)
  • 原文地址:https://www.cnblogs.com/mjtcn/p/8468974.html
Copyright © 2020-2023  润新知