个人认为网络流问题是图论里比较简单的东西!
前几天做了pku 1459,用的比较简单的sap,比较郁闷的是无论如何优化时间老是在1000左右转,后来用dinic,几乎同样的代码,用时差不多是别人的十倍,后来想一下,或许,是stl 的问题。。。
今天验证了一下,不错,就是它的原因,因为sap用广搜来找最短增广路,所以用到了队列,但是队列元素很少,一般的网络流节点个数都是三位数量级的,所以,在一次又一次的用队列时浪费了大量时间,由于数据量很小,手工模拟了一下,时间下降了五倍。。。
200左右,虽说还是很大,总算可以接受了!
1459算是网络流的入门题,一个电力网络,各种各样的节点加上电路,赤裸裸的最大流,额。。。
是无源无汇的网络最大流,这样的最大流就应该给他改一下,因为图中有好多源点,所以加一个强制源点,到各个源点的权值就是源点的值,然后加一个汇点,所有汇点都汇总到这儿,然后求强制源点到最终汇点的最大流就行了!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<string.h>
2 #include<stdio.h>
3 #include<queue>
4 #include<iostream>
5 using namespace std;
6 int cost[105][105],n,m,np,nc,r,pos;
7 int Min[105],pre[105];
8 bool visit[105];
9 int bfs()
10 {
11 int q[105],start = 0,end = 0;
12 memset(visit,false,sizeof(visit));
13 q[0] = n;
14 visit[n] = true;
15 Min[n] = 0x7fffffff;
16 while (start <= end)
17 {
18 int t = q[start];
19 for (int i = 0; i<= n+1; i++)
20 if (!visit[i] && cost[t][i] != 0)
21 {
22 Min[i] = (Min[t] < cost[t][i]) ? Min[t] : cost[t][i];
23 pre[i] = t;
24 if (i == n+1)
25 return Min[n+1];
26 visit[i] = true;
27 q[++end] = i;
28 }
29 start ++;
30 }
31 if (visit[n+1])
32 return Min[n+1];
33 else return -1;
34 }
35 void Ford_Fulkerson()
36 {
37 int max = 0,t,pre_t;
38 while ((r = bfs()) != -1)
39 {
40 max += r;
41 t = n+1;
42 while (t != n)
43 {
44 pre_t = pre[t];
45 cost[pre_t][t] -= r;
46 cost[t][pre_t] += r;
47 t = pre_t;
48 }
49 }
50 printf ("%d\n",max);
51 }
52 int main()
53 {
54 int i,k,x,y;
55 while (scanf ("%d%d%d%d",&n,&np,&nc,&m) != EOF)
56 {
57 memset(cost,0,sizeof(cost));
58 for (i = 0; i < m; i++)
59 {
60 scanf (" (%d,%d)%d",&x,&y,&k);
61 cost[x][y] += k;
62 }
63 for (i = 0; i< np; i++)
64 {
65 scanf (" (%d)%d",&x,&k);
66 cost[n][x] = k;
67 }
68 for (i = 0; i< nc; i++)
69 {
70 scanf (" (%d)%d",&x,&k);
71 cost[x][n+1] = k;
72 }
73 Ford_Fulkerson();
74 }
75 return 0;
76 }
77
78