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

元气小坏坏 提交于 2020-11-22 05:22:37

题目链接

 

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

注意细节,边数组也要算上后加到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 }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!