【BZOJ1001】狼抓兔子(BJOI2006)-平面图最小割转最短路
2017-11-24 16:06
405 查看
测试地址:狼抓兔子
做法:本题需要用到平面图最小割转最短路。
注意到题目中要求一个平面图的最小割,然而这个图点数太多,我们不可能直接用网络流求解,但是我们注意到,如果在平面图中每两个相邻区域之间连双向边(我们把右、上边界和左、下边界看做两个不相邻的平面区域),边的长度为这两个区域的公共边的权值,这时候我们发现,每一个割都对应了一条从右、上边界到左、下边界的路径,因此按这样建图之后跑最短路即可,因为SPFA会被卡,因此用Dijkstra实现即可,时间复杂度为O(nmlog(nm))。注意特判n=1或m=1的情况。
以下是本人代码:
做法:本题需要用到平面图最小割转最短路。
注意到题目中要求一个平面图的最小割,然而这个图点数太多,我们不可能直接用网络流求解,但是我们注意到,如果在平面图中每两个相邻区域之间连双向边(我们把右、上边界和左、下边界看做两个不相邻的平面区域),边的长度为这两个区域的公共边的权值,这时候我们发现,每一个割都对应了一条从右、上边界到左、下边界的路径,因此按这样建图之后跑最短路即可,因为SPFA会被卡,因此用Dijkstra实现即可,时间复杂度为O(nmlog(nm))。注意特判n=1或m=1的情况。
以下是本人代码:
#include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #include <queue> #define inf 1000000000 using namespace std; int n,m,x,first[2000010]={0},tot=0,t,dis[2000010]; struct edge {int v,d,next;} e[12000010]; bool vis[2000010]={0}; struct point { int val,id; bool operator < (point a) const { return val>a.val; } }; priority_queue <point> Q; void insert(int a,int b,int d) { e[++tot].v=b; e[tot].d=d; e[tot].next=first[a]; first[a]=tot; } void dijkstra() { point now,nxt; now.val=0,now.id=0; vis[0]=1,dis[0]=0; for(int i=1;i<=t;i++) dis[i]=inf; for(int i=first[0];i;i=e[i].next) { nxt.val=e[i].d; nxt.id=e[i].v; dis[e[i].v]=e[i].d; Q.push(nxt); } while(!Q.empty()) { now=Q.top(); while(vis[now.id]&&!Q.empty()) Q.pop(),now=Q.top(); if (Q.empty()) break; vis[now.id]=1; for(int i=first[now.id];i;i=e[i].next) if (dis[e[i].v]>dis[now.id]+e[i].d) { dis[e[i].v]=dis[now.id]+e[i].d; nxt.id=e[i].v; nxt.val=dis[e[i].v]; Q.push(nxt); } } } int main() { scanf("%d%d",&n,&m); t=2*(n-1)*(m-1)+1; int minx=inf; for(int i=1;i<m;i++) { scanf("%d",&x); minx=min(x,minx); insert(0,i,x); } for(int i=1;i<n-1;i++) { int s=(2*i-1)*(m-1); for(int j=1;j<m;j++) { scanf("%d",&x); minx=min(minx,x); insert(s+j,s+j+m-1,x); insert(s+j+m-1,s+j,x); } } for(int i=1;i<m;i++) { scanf("%d",&x); minx=min(minx,x); insert((2*n-3)*(m-1)+i,t,x); } for(int i=1;i<n;i++) { int s=(2*i-1)*(m-1); scanf("%d",&x); minx=min(minx,x); insert(s+1,t,x); for(int j=2;j<m;j++) { scanf("%d",&x); minx=min(minx,x); insert(s+j,s+j-m,x); insert(s+j-m,s+j,x); } scanf("%d",&x); minx=min(minx,x); insert(0,s,x); } for(int i=1;i<n;i++) { int s=(2*i-1)*(m-1); for(int j=1;j<m;j++) { scanf("%d",&x); minx=min(minx,x); insert(s+j,s+j-m+1,x); insert(s+j-m+1,s+j,x); } } if (n==1||m==1) {printf("%d",minx);return 0;} dijkstra(); printf("%d",dis[t]); return 0; }
相关文章推荐
- BZOJ 1001: [BeiJing2006]狼抓兔子(平面图最小割转对偶图最短路)
- 【BZOJ1001】狼抓兔子(平面图转对偶图,最短路,最小割)
- BZOJ 1001 狼抓兔子 [最小割转最短路=平面图转对偶图]
- BZOJ1001 [BeiJing2006]狼抓兔子(平面图最小割转最短路)
- BZOJ_1001_狼抓兔子_(平面图求最小割+对偶图求最短路)
- bzoj1001 [BeiJing2006]狼抓兔子(最小割/平面图最大流转对偶图最短路)
- 【BZOJ1001】狼抓兔子(平面图最小割转最短路)
- BZOJ 1001: [BeiJing2006]狼抓兔子(s-t平面图+最短路求最小割)
- BZOJ 1001 狼抓兔子 (网络流最小割/平面图的对偶图的最短路)
- 【平面图】【最小割】【最短路】【Heap-Dijkstra】bzoj1001 [BeiJing2006]狼抓兔子
- 【BZOJ1001】【Beijing2006】狼抓兔子(平面图转对偶图:最小割+最短路)
- 【BZOJ1001】狼抓兔子,平面图转对偶图(从最小割到最短路)
- 狼抓兔子 BZOJ1001 平面图最小割转对偶图最短路
- bzoj 1001: [BeiJing2006]狼抓兔子 对偶图最短路-(最小割)
- BZOJ 1001 狼抓兔子 【平面最小割转最短路】
- 【BZOJ1001】狼抓兔子(平面图转对偶图,最短路)
- 【最小割+对偶图=最短路】BZOJ1001 [BeiJing2006]狼抓兔子
- 【平面图转对偶图】【最短路】【Beijing 2006】【bzoj 1001】狼抓兔子
- 【平面图最小割】BZOJ1001- [BeiJing2006]狼抓兔子
- BZOJ-1001 狼抓兔子 (最小割-最大流)平面图转对偶图+SPFA