最小费用最大流

https://www.luogu.org/problemnew/show/P3381

1.SPFA

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <ctime>
  5 #include <cstring>
  6 #include <string>
  7 #include <map>
  8 #include <set>
  9 #include <list>
 10 #include <queue>
 11 #include <stack>
 12 #include <vector>
 13 #include <bitset>
 14 #include <algorithm>
 15 #include <iostream>
 16 using namespace std;
 17 #define ll long long
 18 const int maxn=5e3+10;
 19 const int inf=1e9;
 20 
 21 struct node
 22 {
 23     int d,len;
 24     ll cost;
 25     node *next,*opp;
 26 }*e[maxn],*pre[maxn];
 27 
 28 int flow=0,s,t,add[maxn];
 29 ll fee=0,dist[maxn];
 30 queue<int> st;
 31 bool vis[maxn];
 32 
 33 void add_edge(int x,int y,int len,ll cost)
 34 {
 35     node *p1=(node*) malloc (sizeof(node));
 36     node *p2=(node*) malloc (sizeof(node));
 37 
 38     p1->d=y;
 39     p1->len=len;
 40     p1->cost=cost;
 41     p1->next=e[x];
 42     p1->opp=p2;
 43     e[x]=p1;
 44 
 45     p2->d=x;///注意
 46     p2->len=0;///注意
 47     p2->cost=-cost;///注意
 48     p2->next=e[y];
 49     p2->opp=p1;
 50     e[y]=p2;
 51 }
 52 
 53 ///可证明此方法能找到最大流,同时这是方式是费用最小的
 54 
 55 void bfs()
 56 {
 57     int d,dd;
 58     node *p;
 59     while (1)
 60     {
 61         memset(dist,0x7f,sizeof(dist));
 62         memset(add,0,sizeof(add));
 63         dist[s]=0;
 64         add[s]=inf; vis[s]=1;
 65         st.push(s);
 66         while (!st.empty())
 67         {
 68             ///保证能扩展的点,add[d]>0
 69             d=st.front();
 70             st.pop();
 71             p=e[d];
 72             while (p)
 73             {
 74                 dd=p->d;
 75                 if (p->len>0 && dist[dd]>dist[d]+p->cost)///注意
 76                 {
 77                     dist[dd]=dist[d]+p->cost;
 78                     add[dd]=min(add[d],p->len);
 79                     pre[dd]=p->opp;
 80                     if (!vis[dd])
 81                     {
 82                         vis[dd]=1;
 83                         st.push(dd);
 84                     }
 85                 }
 86                 p=p->next;
 87             }
 88             vis[d]=0;///
 89         }
 90 
 91         if (add[t]==0)
 92             break;
 93 
 94         flow+=add[t];
 95         fee+=add[t]*dist[t];
 96         d=t;
 97         while (d!=s)
 98         {
 99             pre[d]->len+=add[t];///
100             pre[d]->opp->len-=add[t];
101             d=pre[d]->d;
102         }
103     }
104 }
105 
106 int main()
107 {
108     int n,m,x,y,z;
109     ll w;
110     scanf("%d%d%d%d",&n,&m,&s,&t);
111     while (m--)
112     {
113         scanf("%d%d%d%lld",&x,&y,&z,&w);
114         add_edge(x,y,z,w);
115     }
116     bfs();
117     printf("%d %lld",flow,fee);
118     return 0;
119 }

2.BellmanFord TLE

 1 /**
 2 BellmanFord TLE
 3 **/
 4 #include <cstdio>
 5 #include <cstdlib>
 6 #include <cmath>
 7 #include <cstring>
 8 #include <time.h>
 9 #include <string>
10 #include <set>
11 #include <map>
12 #include <list>
13 #include <stack>
14 #include <queue>
15 #include <vector>
16 #include <bitset>
17 #include <ext/rope>
18 #include <algorithm>
19 #include <iostream>
20 using namespace std;
21 #define ll long long
22 #define minv 1e-6
23 #define inf 1e18
24 #define pi 3.1415926536
25 #define nl 2.7182818284
26 const ll mod=1e9+7;//998244353
27 const int maxn=5e3+10;
28 const int maxm=5e4+10;
29 
30 struct node
31 {
32     int x,y;
33     ll len,fee;
34 }e[maxm<<1];
35 
36 int n,m,s,t,pre[maxn];
37 ll flow=0,fee=0,add[maxn],dist[maxn];
38 
39 bool bell()
40 {
41     bool v=0;
42     int i;
43     for (i=1;i<=m;i++)
44         if (dist[e[i].y]>dist[e[i].x]+e[i].fee && e[i].len>0)
45         {
46             dist[e[i].y]=dist[e[i].x]+e[i].fee;
47             add[e[i].y]=min(add[e[i].x],e[i].len);
48             pre[e[i].y]=i;
49             v=1;
50         }
51     return v;
52 }
53 
54 void change()
55 {
56     int d;
57     flow+=add[t];
58     fee+=1ll*dist[t]*add[t];
59     d=t;
60     while (d!=s)
61     {
62         e[pre[d]].len-=add[t];
63         if (pre[d] & 1)
64             e[pre[d]+1].len+=add[t];
65         else
66             e[pre[d]-1].len+=add[t];
67         d=e[pre[d]].x;
68     }
69 }
70 
71 int main()
72 {
73     int i;
74     scanf("%d%d%d%d",&n,&m,&s,&t);
75     m<<=1;
76     for (i=1;i<=m;i+=2)
77     {
78         scanf("%d%d%lld%lld",&e[i].x,&e[i].y,&e[i].len,&e[i].fee);
79         e[i+1].x=e[i].y;
80         e[i+1].y=e[i].x;
81         e[i+1].len=0;
82         e[i+1].fee=-e[i].fee;
83     }
84     add[s]=inf;
85     while (1)
86     {
87         fill(dist+1,dist+n+1,inf);
88         dist[s]=0;
89         add[t]=0;
90         for (i=1;i<=n;i++)
91             if (!bell() && add[t]!=0)
92                 break;
93         if (i==n+1)
94             break;
95         change();
96     }
97     printf("%lld %lld",flow,fee);
98     return 0;
99 }

3.有负边,不能用Dijkstra。

原文地址:https://www.cnblogs.com/cmyg/p/9569556.html