【模板】最小费用最大流

洛谷模板题

没什么好说的,用spfa来找增广路。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 
  5 using namespace std;
  6 
  7 const int INF = 1 << 26;
  8 int n, m, s, t, cnt;
  9 int to[100001], val[100001], next[100001], cost[100001], head[5001], pre[5001], path[5001], dis[5001];
 10 //pre记录前一个节点,path记录边 
 11 bool vis[5001];
 12 
 13 inline int read()//读入优化 
 14 {
 15     int x = 0, f = 1;
 16     char ch = getchar();
 17     while(ch < '0' || ch > '9')
 18     {
 19         if(ch == '-') f = -1;
 20         ch = getchar();
 21     }
 22     while(ch >= '0' && ch <= '9')
 23     {
 24         x = x * 10 + ch - '0';
 25         ch = getchar();
 26     }
 27     return x * f;
 28 }
 29 
 30 inline void add(int a, int b, int c, int d)
 31 {
 32     to[cnt] = b;
 33     val[cnt] = c;
 34     cost[cnt] = d;
 35     next[cnt] = head[a];
 36     head[a] = cnt++;
 37 }
 38 
 39 inline bool spfa()
 40 {
 41     int u, i, v;
 42     memset(vis, 0, sizeof(vis));
 43     memset(pre, -1, sizeof(pre));
 44     for(i = 1; i <= n; i++) dis[i] = INF;
 45     dis[s] = 0;
 46     queue <int> q;
 47     q.push(s);
 48     vis[s] = 1;
 49     while(!q.empty())
 50     {
 51         u = q.front();
 52         vis[u] = 0;
 53         q.pop();
 54         for(i = head[u]; i != -1; i = next[i])
 55         {
 56             v = to[i];
 57             if(val[i] > 0 && dis[v] > dis[u] + cost[i])
 58             {
 59                 dis[v] = dis[u] + cost[i];
 60                 pre[v] = u;
 61                 path[v] = i;
 62                 if(!vis[v])
 63                 {
 64                     q.push(v);
 65                     vis[v] = 1;
 66                 }
 67             }
 68         }
 69     }
 70     return pre[t] != -1;
 71 }
 72 
 73 int main()
 74 {
 75     int i, j, a, b, c, d, money = 0, flow = 0, f;
 76     n = read();
 77     m = read();
 78     s = read();
 79     t = read();
 80     memset(head, -1, sizeof(head));
 81     for(i = 1; i <= m; i++)
 82     {
 83         a = read();
 84         b = read();
 85         c = read();
 86         d = read();
 87         add(a, b, c, d);
 88         add(b, a, 0, -d);
 89     }
 90     while(spfa())
 91     {
 92         f = INF;
 93         for(i = t; i != s; i = pre[i]) f = min(f, val[path[i]]);
 94         flow += f;
 95         money += dis[t] * f;
 96         for(i = t; i != s; i = pre[i])
 97         {
 98             val[path[i]] -= f;
 99             val[path[i] ^ 1] += f;
100         }
101     }
102     printf("%d %d", flow, money);
103     return 0;
104 }
View Code

但是spfa对于稠密图的处理效果不是很好,所以改用dijkstra+stl堆优化,至少快了些。。

——代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 #define Heap pair<int, int>
 5 
 6 using namespace std;
 7 
 8 const int INF = 1 << 26;
 9 int n, m, s, t, cnt;
10 int to[100001], val[100001], next[100001], cost[100001], head[5001], pre[5001], path[5001], dis[5001];
11 //pre记录前一个节点,path记录边 
12 
13 inline int read()//读入优化 
14 {
15     int x = 0, f = 1;
16     char ch = getchar();
17     while(ch < '0' || ch > '9')
18     {
19         if(ch == '-') f = -1;
20         ch = getchar();
21     }
22     while(ch >= '0' && ch <= '9')
23     {
24         x = x * 10 + ch - '0';
25         ch = getchar();
26     }
27     return x * f;
28 }
29 
30 inline void add(int a, int b, int c, int d)
31 {
32     to[cnt] = b;
33     val[cnt] = c;
34     cost[cnt] = d;
35     next[cnt] = head[a];
36     head[a] = cnt++;
37 }
38 
39 bool Dijkstra()
40 {
41     int i, v;
42     Heap u;
43     memset(pre, -1, sizeof(pre));
44     for(i = 1; i <= n; i++) dis[i] = INF;
45     dis[s] = 0;
46     priority_queue <Heap, vector <Heap>, greater <Heap> > q;
47     q.push(make_pair(0, s));//前一个表示当前节点到起点的距离,后一个是当前节点 
48     while(!q.empty())
49     {
50         u = q.top();
51         q.pop();
52         if(u.first != dis[u.second]) continue; 
53         for(i = head[u.second]; i != -1; i = next[i])
54         {
55             v = to[i];
56             if(val[i] > 0 && dis[v] > dis[u.second] + cost[i])
57             {
58                 dis[v] = dis[u.second] + cost[i];
59                 pre[v] = u.second;
60                 path[v] = i;
61                 q.push(make_pair(dis[v], v));
62             }
63         }
64     }
65     return pre[t] != -1;
66 }
67 
68 int main()
69 {
70     int i, j, a, b, c, d, money = 0, flow = 0, f;
71     n = read();
72     m = read();
73     s = read();
74     t = read();
75     memset(head, -1, sizeof(head));
76     for(i = 1; i <= m; i++)
77     {
78         a = read();
79         b = read();
80         c = read();
81         d = read();
82         add(a, b, c, d);
83         add(b, a, 0, -d);
84     }
85     while(Dijkstra())
86     {
87         f = INF;
88         for(i = t; i != s; i = pre[i]) f = min(f, val[path[i]]);
89         flow += f;
90         money += dis[t] * f;
91         for(i = t; i != s; i = pre[i])
92         {
93             val[path[i]] -= f;
94             val[path[i] ^ 1] += f;
95         }
96     }
97     printf("%d %d", flow, money);
98     return 0;
99 }
View Code

洛谷改了数据之后dijk居然T了。。

原文地址:https://www.cnblogs.com/zhenghaotian/p/6690154.html