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;
}