标签:
题目大概说给一个n×n的方格,边有权值,问从求(1,1)到(n,n)的最小割。
点达到了160000个,直接最大流不好。这题的图是平面图,求最小割可以转化成求其对偶图的最短路,来更高效地求解:
首先源点汇点间新加一条边,然后构造其对偶图:
这样可以发现,对偶图的源点到汇点的一条路径就对应这原图的源点到汇点的一个割边集,而最短路就对应最小割了。所以求一下最小割就OK了,我用SPFA好像超时了,改用堆优化的Dijkstra,10W个点OK。
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 using namespace std; 6 #define INF (1<<30) 7 #define MAXN 1111*1111 8 struct Edge{ 9 int v,w,next; 10 }edge[MAXN<<1]; 11 int vs,vt,NV,NE,head[MAXN]; 12 void addEdge(int u,int v,int w){ 13 edge[NE].v=v; edge[NE].w=w; edge[NE].next=head[u]; 14 head[u]=NE++; 15 } 16 struct Node{ 17 int u,d; 18 Node(int _u=0,int _d=0):u(_u),d(_d){} 19 bool operator<(const Node &nd)const{ 20 return nd.d<d; 21 } 22 }; 23 int d[MAXN]; 24 bool vis[MAXN]; 25 int dijkstra(){ 26 for(int i=0; i<NV; ++i){ 27 d[i]=INF; vis[i]=0; 28 } 29 d[vs]=0; 30 priority_queue<Node> que; 31 que.push(Node(vs,0)); 32 while(!que.empty()){ 33 Node nd=que.top(); que.pop(); 34 if(nd.u==vt) return nd.d; 35 if(vis[nd.u]) continue; 36 vis[nd.u]=1; 37 for(int i=head[nd.u]; i!=-1; i=edge[i].next){ 38 int v=edge[i].v; 39 if(vis[v]) continue; 40 if(d[v]>d[nd.u]+edge[i].w){ 41 d[v]=d[nd.u]+edge[i].w; 42 que.push(Node(v,d[v])); 43 } 44 } 45 } 46 return INF; 47 } 48 int a[444][444]; 49 int main(){ 50 int t,n; 51 scanf("%d",&t); 52 while(t--){ 53 scanf("%d",&n); 54 if(n==1){ 55 puts("0"); 56 continue; 57 } 58 vs=(n-1)*(n-1); vt=vs+1; NV=vt+1; NE=0; 59 memset(head,-1,sizeof(head)); 60 for(int i=0; i<n; ++i){ 61 for(int j=0; j<n; ++j){ 62 scanf("%d",&a[i][j]); 63 } 64 } 65 for(int i=0; i<n-1; ++i){ 66 for(int j=0; j<n; ++j){ 67 if(j==0){ 68 addEdge(vs,i*(n-1)+j,a[i][j]); 69 }else if(j==n-1){ 70 addEdge(i*(n-1)+j-1,vt,a[i][j]); 71 }else{ 72 addEdge(i*(n-1)+j,i*(n-1)+j-1,a[i][j]); 73 addEdge(i*(n-1)+j-1,i*(n-1)+j,a[i][j]); 74 } 75 } 76 } 77 for(int j=0; j<n-1; ++j){ 78 for(int i=0; i<n; ++i){ 79 if(i==0){ 80 addEdge(i*(n-1)+j,vt,a[i][j]); 81 }else if(i==n-1){ 82 addEdge(vs,(i-1)*(n-1)+j,a[i][j]); 83 }else{ 84 addEdge(i*(n-1)+j,(i-1)*(n-1)+j,a[i][j]); 85 addEdge((i-1)*(n-1)+j,i*(n-1)+j,a[i][j]); 86 } 87 } 88 } 89 printf("%d\n",dijkstra()); 90 } 91 return 0; 92 }
HDU3870 Catch the Theves(平面图最小割转最短路)
标签:
原文地址:http://www.cnblogs.com/WABoss/p/5455721.html