【HDU3870 Catch the Theves】 最小割与最短路模型进行转换

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3870

题目大意:O(-1).

解题思路:开始直接构图,套Dinic()模板,悲剧的TLE。再认真看看题,n为400,也就是有400*400个点,边大概是节点的4倍大小,明显最大流会TLE,对偶图构图很蛋疼。

               对于点数边数很大的求最小割来说,可以构造它的对偶图,构造对偶图要求原图中s和d必须在图的外侧,对偶图G*中的每个点对应G中一个面,每一条从st到sd的最短路径都对应原图s到d的一个最小割。

 构造对偶图条件:

1、原图是一个平面图

2、图中的一个点为源点s,另外一个点为汇点t,且s和t都在图中的无界面的边界上

    G*中的每个点对应G中一个面

参考文献:周冬《两极相通——浅析最大—最小定理在信息学竞赛中的应用》.

View Code
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int mn=422222;
 8 const int mm=2111111;
 9 const int oo=0x3fffffff;
10 int que[mn], inque[mn], dis[mn];
11 int head[mn], reach[mm], flow[mm], next[mm];
12 int st, sd, edge;
13 int val[444][444];
14 
15 void addedge(int u, int v, int c1, int c2)
16 {
17     reach[edge]=v, flow[edge]=c1, next[edge]=head[u], head[u]=edge++;
18     reach[edge]=u, flow[edge]=c2, next[edge]=head[v], head[v]=edge++;
19 }
20 
21 void spfa()
22 {
23     for(int i=1; i<=sd+5; i++) inque[i]=0, dis[i]=oo;
24     int h=0, t=0;
25     dis[st]=0;
26     que[t++]=st;
27     inque[st]=1;
28     while(h!=t)
29     {
30         int u=que[h++];
31         if(h==mn) h=0;  ///!循环队列
32         inque[u]=0;
33         for(int i=head[u]; i>=0; i=next[i])
34         {
35             int v=reach[i], val=flow[i];
36             if(dis[v]>dis[u]+val)  ///当满足这个条件时才进行下面的操作
37             {
38                 dis[v]=dis[u]+val; ///松弛操作
39                 if(!inque[v])
40                 {
41                     inque[v]=1;
42                     que[t++]=v;
43                     if(t==mn) t=0; ///循环队列
44                 }
45             }
46         }
47     }
48 }
49 
50 int main()
51 {
52     int n, m, T;
53     cin >> T;
54     while(T--)
55     {
56         scanf("%d",&n);
57         st=0, sd=n*n+1;
58         memset(head,-1,sizeof(head));
59         for(int i=1; i<=n; i++)
60             for(int j=1; j<=n; j++) scanf("%d",&val[i][j]);
61         for(int i=1; i<n; i++)
62         {
63             addedge(st,i,val[1][i],val[1][i]);
64             addedge(st,(i-1)*(n-1)+(n-1),val[i][n],val[i][n]);
65             addedge((i-1)*(n-1)+1,sd,val[i][1],val[i][1]);
66             addedge((n-2)*(n-1)+i,sd,val[n][i],val[n][i]);
67         }
68         for(int i=1; i<=n-1; i++)
69             for(int j=1; j<=n-1; j++)
70             {
71                 if(j+1<=n-1)addedge((i-1)*(n-1)+j,(i-1)*(n-1)+j+1,val[i][j+1],val[i][j+1]);
72                 if(i+1<=n-1)addedge((i-1)*(n-1)+j,i*(n-1)+j,val[i+1][j],val[i+1][j]);
73             }
74         spfa();
75         printf("%d\n",dis[sd]);
76     }
77     return 0;
78 }
原文地址:https://www.cnblogs.com/kane0526/p/3056473.html