【SDOI2009】晨跑

费用流
(默认你已经会了最大流)
费用流,即在最大流的基础上,选择权值min值.
我们可以用spfa做最大流(近似ek),权值=单价*距离
代码奉上
1 bool bfs(int s,int t)
2 {
3 f(i,1,2*n)
4 {
5 dis[i]=flow[i]=inf;
6 }
7 int head=0,tail=1;
8 c[1]=s;vis[s]=++tot;
9 dis[s]=0;fa[t]=-1;
10 while(head<tail)
11 {
12 int x=c[++head];
13 vis[x]=0;
14 for(int i=h[x];i;i=e[i].next)
15 {
16 int y=e[i].to;
17 if(e[i].flow&&dis[x]+e[i].dis<dis[y])
18 {
19 dis[y]=dis[x]+e[i].dis;
20 fa[y]=x;
21 last[y]=i;
22 flow[y]=min(flow[x],(long long)e[i].flow);
23 if(vis[y]!=tot)
24 {
25 vis[y]=tot;
26 c[++tail]=y;
27 }
28 }
29 }
30 }
31 return fa[t]!=-1;
32 }
33 void mcmf(int s,int t)
34 {
35 while(bfs(s,t))
36 {
37 maxflow+=flow[t];
38 mincost+=flow[t]*dis[t];
39 for(int i=fa[t];i!=s;i=fa[i])
40 {
41 e[last[i]].flow-=flow[t];
42 e[last[i]^1].flow+=flow[t];
43 }
44 }
45 }
本题思路
网络流难在建图,核心部分copy就好了:
由于本题特殊性,我们采用割点,即x->y+n->n
并且每条边流量为1/0
如下图,前者为流量,后者为权值
然后跑一边费用流即可
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #define inf 1000000000
5 #define S 1
6 #define T n
7 #define f(i,a,b) for(register int i=a,x,y,z;i<=b;++i)
8 #define read(a) scanf("%d",&a)
9 using namespace std;
10 int n,m,h[1005],cnt=1,fa[1005];
11 long long ans,flow[1005],tot,c[10005],vis[1005],dis[1005],last[1005],maxflow,mincost;
12 struct node
13 {
14 int next,to,flow,dis;
15 }e[100005];
16 void add(int x,int y,int flow,int dis)
17 {
18 e[++cnt].to=y;
19 e[cnt].flow=flow;
20 e[cnt].dis=dis;
21 e[cnt].next=h[x];
22 h[x]=cnt;
23 }
24 bool bfs(int s,int t)
25 {
26 f(i,1,2*n)
27 {
28 dis[i]=flow[i]=inf;
29 }
30 int head=0,tail=1;
31 c[1]=s;vis[s]=++tot;
32 dis[s]=0;fa[t]=-1;
33 while(head<tail)
34 {
35 int x=c[++head];
36 vis[x]=0;
37 for(int i=h[x];i;i=e[i].next)
38 {
39 int y=e[i].to;
40 if(e[i].flow&&dis[x]+e[i].dis<dis[y])
41 {
42 dis[y]=dis[x]+e[i].dis;
43 fa[y]=x;
44 last[y]=i;
45 flow[y]=min(flow[x],(long long)e[i].flow);
46 if(vis[y]!=tot)
47 {
48 vis[y]=tot;
49 c[++tail]=y;
50 }
51 }
52 }
53 }
54 return fa[t]!=-1;
55 }
56 void mcmf(int s,int t)
57 {
58 while(bfs(s,t))
59 {
60 maxflow+=flow[t];
61 mincost+=flow[t]*dis[t];
62 for(int i=fa[t];i!=s;i=fa[i])
63 {
64 e[last[i]].flow-=flow[t];
65 e[last[i]^1].flow+=flow[t];
66 }
67 }
68 }
69 int main()
70 {
71 read(n);read(m);
72 f(i,1,m)
73 {
74 read(x);
75 read(y);
76 read(z);
77 add(x,y+n,1,z);
78 add(y+n,x,0,-z);
79 }
80 f(i,1,n)
81 {
82 add(i+n,i,1,0);
83 add(i,i+n,0,0);
84 }
85 mcmf(S,T);
86 printf("%lld %lld",maxflow,mincost);
87 }