最小费用最大流
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。