After the long vacation, the maze designer master has to do his job. A tour company gives him a map which is a rectangle. The map consists of N×M little squares. That is to say, the height of the rectangle is N and the width of the rectangle is M. The master knows exactly how the maze is going to use. The tour company will put a couple in two different squares in the maze and make them seek each other. Of course,the master will not make them find each other easily. The only thing the master does is building some wall between some little squares. He knows in that way, wherever the couple is put, there is only one path between them. It is not a difficult thing for him, but he is a considerate man. He also knows that the cost of building every wall between two adjacent squares is different(Nobody knows the reason). As a result, he designs the maze to make the tour company spend the least money to build it.
Now, here's your part. The tour company knows you're the apprentice of the master, so they give you a task. you're given Q qustions which contain the information of where the couple will be put. You need to figure out the length of the shortest path between them.
However,the master doesn't tell you how he designs the maze, but he believes that you, the best student of himself, know the way. So he goes on vacation again.
Input
The first line of the input contains two integers N and M (1≤N,M≤500), giving the number of rows and columns of the maze.
The next N×M lines of the input give the information of every little square in the maze, and their coordinates are in order of (1,1), (1,2) ⋯⋯ (1,M) , (2,1), (2,2) , ⋯⋯ , (2,M) , ⋯⋯ ,(N,M).
Each line contains two characters DDD and RRR and two integers aaa , bbb (0≤a,b≤20000000000 \le a,b \le 20000000000≤a,b≤2000000000 ), aaa is the cost of building the wall between it and its lower adjacent square, and bbb is the cost of building the wall between it and its right adjacent square. If the side is boundary, the lacking path will be replaced with X 000.
The next line contains an integer Q (1≤Q≤100000 ), which represents the number of questions.
The next Q lines gives four integers, x1, y1, x2, y2 ( 1≤x1, x2≤N , 1≤y1 ,y2≤M), which represent two squares and their coordinate are (x1 , y1) and (x2 , y2).
(x,y) means row x and column y.
It is guaranteed that there is only one kind of maze.
Output
For each question, output one line with one integer which represents the length of the shortest path between two given squares.
样例输入
3 3
D 1 R 9
D 7 R 8
D 4 X 0
D 2 R 6
D 12 R 5
D 3 X 0
X 0 R 10
X 0 R 11
X 0 X 0
3
1 1 3 3
1 2 3 2
2 2 3 1
样例输出
4
2
2
题意:
给你一颗n*m的矩阵,除了墙壁之外的每条边都有一个建造费用,现在给你两个坐标,现在要你把造出一些墙,让这两个坐标之间只有一条路能够到达,并且修建墙的费用最小。
做法:
比赛的时候看了一眼这个题,好像感觉可以做,但是最后还是没想到,果然还是太笨了。。机房里的大佬都是一眼题呀。。因为要使建造的墙壁费用最小,那么就假设所有的墙壁都已经建好了,去在这两个坐标之间挖出一条路,很明显肯定要先挑选费用大的墙壁去挖,所以我们就可以先预处理出一颗最大生成树(即让权值大的边先连接起来),构造出一棵树之后,求两点的坐标就是求树上距离,很明显就是LCA了,这就是一道最大生成树+LCA的板子题。。。天哪。。注意边容易开小。
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=250020;
int ffa[maxn];
int n,m,dep[maxn],fa[maxn][25],now;
ll dist[maxn],head[maxn];
struct node{
int from,to,next;
int val;
}e[maxn<<1];
struct tree{
int u,v;
ll w;
bool operator < (const tree &a) const {
return w>a.w;
}
}edge[maxn<<2];
int fin(int x){
return ffa[x]==0?x:ffa[x]=fin(ffa[x]);
}
void add(int u,int v,int w){
e[now].val=w,e[now].from=u,e[now].to=v;
e[now].next=head[u],head[u]=now++;
}
void dfs(int now,int f,int deps){
dep[now]=deps;
fa[now][0]=f;
for(int i=head[now];~i;i=e[i].next){
int u=e[i].to,w=e[i].val;
if(u==f) continue;
if(!dist[u]){
dist[u]=dist[now]+w;
dfs(u,now,deps+1);
}
}
}
void solve(){
for(int j=1;(1<<j)<=n*m;j++)
for(int i=1;i<=n*m;i++)
if(fa[i][j-1]!=-1) fa[i][j]=fa[fa[i][j-1]][j-1];
}
int LCA(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=23;i>=0;i--)
if(dep[fa[x][i]]>=dep[y])
x=fa[x][i];
if(x==y) return x;
for(int i=23;i>=0;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int getdist(int x,int y){
//cout<<LCA(x,y)<<endl;
return dist[x]+dist[y]-2*dist[LCA(x,y)];
}
int gainp(int x,int y){
return (x-1)*m+y;
}
int main(){
char s1[5],s2[5];
memset(head,-1,sizeof(head));
ll a,b,sum=0;
scanf("%d%d",&n,&m);
int cn=0,q;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%s%lld%s%lld",s1,&a,s2,&b);
edge[cn++]={gainp(i,j),gainp(i+1,j),a};
edge[cn++]={gainp(i,j),gainp(i,j+1),b};
}
}
scanf("%d",&q);
sort(edge,edge+cn);
for(int i=0,nows=0;i<cn;i++){
int fu=fin(edge[i].u),fv=fin(edge[i].v);
if(fu!=fv) {
add(edge[i].u,edge[i].v,1);
add(edge[i].v,edge[i].u,1);
ffa[fu]=fv;
if(++nows==n*m-1) break;
}
}
for(int j=1;(1<<j)<=n*m;j++)
for(int i=1;i<=n*m;i++)
fa[i][j]=-1;
dist[1]=1;
dfs(1,-1,1);
solve();
while(q--){
int x1,x2,y1,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int aim1=gainp(x1,y1),aim2=gainp(x2,y2);
printf("%d\n",getdist(aim1,aim2));
}
return 0;
}