BZOJ 1001: [BeiJing2006]狼抓兔子(最短路)

传送门

解题思路

  平面图转对偶图,然后跑最短路。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>

using namespace std;
const int N=1405;

inline int rd(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return f?x:-x;
}

int n,m,head[N*N],cnt,to[N*N*6],nxt[N*N*6],val[N*N*6];
int S,T,dis[N*N],Min=1e9;
bool vis[N*N];

struct Node{
	int id,w;
	friend bool operator<(const Node A,const Node B){
		return A.w>B.w;
	}
	Node(int _id=0,int _w=0){id=_id;w=_w;}
};
priority_queue<Node> Q;

inline void add(int bg,int ed,int w){
	to[++cnt]=ed,nxt[cnt]=head[bg],val[cnt]=w,head[bg]=cnt;
	to[++cnt]=bg,nxt[cnt]=head[ed],val[cnt]=w,head[ed]=cnt;
}

void dijkstra(){
	memset(dis,0x3f,sizeof(dis));
	dis[S]=0; Q.push(Node(S,0));
	while(Q.size()){
		Node now=Q.top(); Q.pop();
		if(dis[now.id]!=now.w || vis[now.id]) continue;
		int x=now.id;vis[x]=1;
		for(int i=head[x];i;i=nxt[i]){
			int u=to[i];
			if(dis[x]+val[i]<dis[u]){
				dis[u]=dis[x]+val[i];
				Q.push(Node(u,dis[u]));
			}
		}
	}
}

int main(){
	n=rd(),m=rd(); int w; S=0;T=2*(n-1)*(m-1)+1;
	if(n==1 && m==1) {puts("0");return 0;}
	for(int i=1;i<=n;i++)
		for(int j=1;j<m;j++){scanf("%d",&w); Min=min(Min,w);
			if(i==1) add(2*j,T,w);
			else if(i==n) add(S,(i-2)*2*(m-1)+2*j-1,w);
			else add((i-2)*2*(m-1)+2*j-1,(i-1)*2*(m-1)+2*j,w);
		}
	for(int i=1;i<n;i++)
		for(int j=1;j<=m;j++){scanf("%d",&w); Min=min(Min,w);
			if(j==1) add(S,(i-1)*2*(m-1)+2*j-1,w);
			else if(j==m) add((i-1)*2*(m-1)+2*(j-1),T,w);
			else add((i-1)*2*(m-1)+2*(j-1),(i-1)*2*(m-1)+2*j-1,w);
		}
	if(n==1 || m==1) {printf("%d\n",Min);return 0;}
	for(int i=1;i<n;i++)
		for(int j=1;j<m;j++){scanf("%d",&w);
			add((i-1)*2*(m-1)+2*j-1,(i-1)*2*(m-1)+2*j,w);
		}
	dijkstra(); printf("%d\n",dis[T]);
	return 0;
}
posted @ 2019-01-21 16:01  Monster_Qi  阅读(130)  评论(0编辑  收藏  举报