【洛谷 p3381】模板-最小费用最大流(图论)

题目:给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。

解法:在Dinic的基础下做spfa算法。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<queue>
 6 using namespace std;
 7 
 8 const int N=5010,M=50010,INF=(int)1e9;
 9 int n,m,st,ed,len=1;
10 int last[N],vis[N],id[N],pre[N],flow[N],d[N];
11 struct node{int y,fl,co,next;}a[2*M];
12 queue<int> q;
13 
14 int mmin(int x,int y) {return x<y?x:y;}
15 void ins(int x,int y,int fl,int co)
16 {
17     a[++len].y=y,a[len].fl=fl,a[len].co=co;
18     a[len].next=last[x],last[x]=len;
19     a[++len].y=x,a[len].fl=0,a[len].co=-co;
20     a[len].next=last[y],last[y]=len;
21 }
22 bool spfa()
23 {
24     while (!q.empty()) q.pop();
25     for (int i=1;i<=n;i++) d[i]=INF;
26     memset(vis,0,sizeof(vis));
27     q.push(st);
28     d[st]=0,vis[st]=1,flow[st]=INF;
29     while (!q.empty())
30     {
31       int x=q.front();
32       q.pop(); vis[x]=0;
33       for (int i=last[x];i!=-1;i=a[i].next)
34       {
35         int y=a[i].y;
36         if (!a[i].fl) continue;
37         if (d[x]+a[i].co<d[y])
38         {
39           d[y]=d[x]+a[i].co;
40           flow[y]=mmin(flow[x],a[i].fl);
41           id[y]=i, pre[y]=x;
42           if (!vis[y]) q.push(y), vis[y]=1;
43         }
44       }
45     }
46     return (d[ed]!=INF);
47 }
48 void Max_flow()
49 {
50     int sum=0,cost=0;;
51     while (spfa())
52     {
53       sum+=flow[ed],cost+=d[ed]*flow[ed];
54       for (int i=ed;i!=st;i=pre[i])
55       {
56         a[id[i]].fl-=flow[ed];
57         a[id[i]^1].fl+=flow[ed];
58       }
59     }
60     printf("%d %d
",sum,cost);
61 }
62 int main()
63 {
64     scanf("%d%d%d%d",&n,&m,&st,&ed);
65     int x,y,fl,co;
66     memset(last,-1,sizeof(last));
67     for (int i=1;i<=m;i++)
68     {
69       scanf("%d%d%d%d",&x,&y,&fl,&co);
70       ins(x,y,fl,co);
71     }
72     Max_flow();
73     return 0;
74 }