网络流--构图的巧和美

  求最大流的算法有好多种,sap,dinic,啥的只要会原理基本上就能想的出来,网络流,有时候就难在构建模型上,怎么构建流网络保证网络的正确性及最大流的最优性是构图题的重要特点!今天做了两道构图题,不得不说这类题很锻炼人的思维能力,如下:

pku 3281:

  农场主给牛牛们准备来了f种食物和d种饮料,每种只有一份,牛牛们对不同的食物和饮料各有所爱,求能找到理想中的食物和饮料的牛牛的最大数目。

  这道题是很裸的最大流,题意很明确,我就卡在两种条件的限制上,后来看网络上的大牛的解法是把牛看做节点然后拆成两排,一排与食物相连一排与饮料相连,拆开的牛之间再连一条边,权值为1。很巧妙的构图!

 

代码
   
     
1 #include < stdio.h >
2 #include < string .h >
3 #include < stdlib.h >
4   #define INF 0x7fffffff
5   int map[ 450 ][ 450 ],pre[ 450 ];
6   int S,T;
7   int Min( int x, int y)
8 {
9 return x > y ? y:x;
10 }
11 int bfs()
12 {
13 int i,start = 0 ,end = 1 ,que[ 450 ],max[ 450 ];
14 bool visit[ 450 ]; max[S] = INF;
15 memset(visit, false , sizeof (visit));
16 que[ 0 ] = S; visit[S] = true ;
17 while (start < end){
18 int t = que[start ++ ];
19 for (i = S; i <= T; i ++ ){
20 if (map[t][i] > 0 && visit[i] == false ){
21 que[end ++ ] = i; visit[i] = true ;
22 max[i] = Min(max[t],map[t][i]);
23 pre[i] = t;
24 if (i == T) return max[i];
25 }
26 }
27 }
28 return - 1 ;
29 }
30 int sap()
31 {
32 int f,ans = 0 ; pre[S] = - 1 ;
33 while ((f = bfs()) != - 1 ){
34 ans += f;
35 int x = T,y = pre[x];
36 while (y != - 1 ){
37 map[y][x] -= f;
38 map[x][y] += f;
39 x = y; y = pre[x];
40 }
41 }
42 return ans;
43 }
44 int main()
45 {
46 int n,f,d,i,j;
47 while (scanf ( " %d%d%d " , & n, & f, & d) != EOF){
48 S = 0 ; T = 2 * n + f + d + 1 ;
49 memset(map, 0 , sizeof (map));
50 for (i = 1 ; i <= f; i ++ ) map[S][i] = 1 ;
51 for (i = f + 2 * n + 1 ; i < T; i ++ ) map[i][T] = 1 ;
52 for (i = f + 1 ; i <= f + n; i ++ ) map[i][i + n] = 1 ;
53 for (i = 1 ; i <= n; i ++ ){
54 int x,y,v,cow = f + i;
55 scanf ( " %d%d " , & x, & y);
56 for (j = 0 ; j < x; j ++ ){
57 scanf ( " %d " , & v);
58 map[v][cow] = 1 ;
59 }
60 for (j = 0 ; j < y; j ++ ){
61 scanf ( " %d " , & v);
62 map[cow + n][f + 2 * n + v] = 1 ;
63 }
64 }
65 int ans = sap();
66 printf ( " %d\n " ,ans);
67 }
68 return 0 ;
69 }
70

 

pku 1149

  题目描述比较繁琐,不再赘述,构图的时候把掌管有同一个猪圈的两个人由先到的向后到的引一条无限流量的边!因为可以随意调整,其他的极限流值可以限制答案的正确性,所以可知这种构图也是正确的。

 

代码
   
     
1 #include < stdio.h >
2 #include < string .h >
3 #include < stdlib.h >
4 #define INF 0xfffffff
5 int map[ 1150 ][ 1150 ],pre[ 1150 ],p[ 1005 ];
6 bool cust[ 1105 ][ 1105 ];
7 int S,T;
8 int Min( int x, int y)
9 {
10 return x > y ? y:x;
11 }
12 int bfs()
13 {
14 int i,start = 0 ,end = 1 ,que[ 1150 ],max[ 1150 ];
15 bool visit[ 1150 ]; max[S] = INF;
16 memset(visit, false , sizeof (visit));
17 que[ 0 ] = S; visit[S] = true ;
18 while (start < end){
19 int t = que[start ++ ];
20 for (i = S; i <= T; i ++ ){
21 if (map[t][i] > 0 && visit[i] == false ){
22 que[end ++ ] = i; visit[i] = true ;
23 max[i] = Min(max[t],map[t][i]);
24 pre[i] = t;
25 if (i == T) return max[i];
26 }
27 }
28 }
29 return - 1 ;
30 }
31 int sap()
32 {
33 int f,ans = 0 ; pre[S] = - 1 ;
34 while ((f = bfs()) != - 1 ){
35 ans += f;
36 int x = T,y = pre[x];
37 while (y != - 1 ){
38 map[y][x] -= f;
39 map[x][y] += f;
40 x = y; y = pre[x];
41 }
42 }
43 return ans;
44 }
45 int main()
46 {
47 int n,m,v,i,j,k,l;
48 while (scanf ( " %d%d " , & m, & n) != EOF){
49 S = 0 ; T = n + m + 1 ;
50 memset(map, 0 , sizeof (map));
51 memset(cust, false , sizeof ( false ));
52 for (i = 1 ; i <= m; i ++ ){
53 scanf ( " %d " , & v);
54 map[S][i] = v;
55 }
56 for (i = 1 ; i <= n; i ++ ){
57 scanf ( " %d " , & k);
58 for (j = 0 ; j < k; j ++ ){
59 scanf ( " %d " , & v);
60 map[v][m + i] = INF;
61 cust[v][i] = true ;
62 for (l = 1 ; l < i; l ++ ){
63 if (cust[v][l] == true )
64 map[m + l][m + i] = INF;
65 }
66 }
67 scanf ( " %d " , & v);
68 map[m + i][T] = v;
69 }
70 int ans = sap();
71 printf ( " %d\n " ,ans);
72 }
73 return 0 ;
74 }
75

 

你可能感兴趣的:(网络流)