https://nanti.jisuanke.com/t/31462
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 \times MN×M little squares. That is to say, the height of the rectangle is NN and the width of the rectangle is MM. 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 QQ 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 NN and MM (1 \le N,M \le 5001≤N,M≤500), giving the number of rows and columns of the maze.
The next N \times MN×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,1) , (1,2)(1,2) \cdots⋯ (1,M)(1,M) , (2,1)(2,1) , (2,2)(2,2) , \cdots⋯ , (2,M)(2,M) , \cdots⋯ ,(N,M)(N,M).
Each line contains two characters DD and RR and two integers aa , bb (0 \le a,b \le 20000000000≤a,b≤2000000000 ), aa is the cost of building the wall between it and its lower adjacent square, and bb 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 00.
The next line contains an integer QQ (1 \le Q \le 1000001≤Q≤100000 ), which represents the number of questions.
The next QQ lines gives four integers, x_1x1, y_1y1, x_2x2, y_2y2 ( 1 \le x_11≤x1 , x_2 \le Nx2≤N , 1 \le y_11≤y1 , y_2 \le My2≤M ), which represent two squares and their coordinate are (x_1x1 , y_1y1) and (x_2x2 , y_2y2).
(xx,yy) means row xx and column yy.
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的矩形,每个格子可以在右边界花费x建一堵墙,在下边界花费y建一堵墙。最终你要保证任意两点间只有一条路径。求花费最小的情况下,Q次查询,每次查询两个点之间的距离。
分析:把网格视做点,不建墙的边视作边权,找到最大生成树,这个时候的边就是选择不建墙的边,所以花费最小。建好树之后,然后套用LCA就行。
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=500010;
int n,m,q,tot,cnt,tmp,ans,N;
int f[maxn][20];
int head[maxn];
ll dis[maxn];
int dep[maxn],e[maxn],pos[maxn],fa[maxn];
bool vis[maxn];
struct node
{
int to,nex;
ll w;
bool operator<(node aa)const
{
return w>aa.w;
}
}a[maxn],aa[maxn];
void add(int u,int v,ll w)
{
a[cnt].to=v;
a[cnt].w=w;
a[cnt].nex=head[u];
head[u]=cnt++;
}
void init()
{
cnt=tot=0;
memset(head,-1,sizeof(head));
memset(pos,-1,sizeof(pos));
memset(vis,0,sizeof(vis));
memset(fa,-1,sizeof(fa));
dis[1]=0;
}
void dfs(int u,int deep)//1
{
if(pos[u]!=-1)return;
pos[u]=tot;e[tot]=u;dep[tot++]=deep;
for(int i=head[u];i!=-1;i=a[i].nex)
{
int v=a[i].to;
if(pos[v]==-1)
{
dfs(v,deep+1);
e[tot]=u;dep[tot++]=deep;
}
}
}
void rmq(int n)//2
{
for(int i=1;i<=n;i++)f[i][0]=i;
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
{
if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]]) f[i][j]=f[i][j-1];
else f[i][j]=f[i+(1<<(j-1))][j-1];
}
}
int RMQ(int l,int r)
{
int k=(int)(log((double)(r-l+1))/log(2.0));
if(dep[f[l][k]]<dep[f[r-(1<<k)+1][k]]) return f[l][k];
else return f[r-(1<<k)+1][k];
}
int lca(int x,int y)//3
{
if(pos[x]<pos[y]) return e[RMQ(pos[x],pos[y])];
else return e[RMQ(pos[y],pos[x])];
}
ll cal(int x,int y)
{
return dep[pos[x]]+dep[pos[y]]-2*dep[pos[lca(x,y)]];
}
int get_id(int i,int j)
{
return (i-1)*m+j;
}
int find(int x){return fa[x]==-1?x:fa[x]=find(fa[x]);}
int main()
{
int T,cas=1;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
int tt=0;
char cc[5],hh[5];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
ll x,y;
scanf("%s %lld %s %lld",cc,&x,hh,&y);
if(cc[0]=='D')
{
aa[tt].to=get_id(i,j);
aa[tt].nex=get_id(i+1,j);
aa[tt++].w=x;
}
if(hh[0]=='R')
{
aa[tt].to=get_id(i,j);
aa[tt].nex=get_id(i,j+1);
aa[tt++].w=y;
}
}
sort(aa,aa+tt);
int opt=0;
n=n*m;
for(int i=0;i<tt&&opt<n-1;i++)
{
int u=aa[i].to;
int v=aa[i].nex;
int faa=find(u);
int fbb=find(v);
if(faa!=fbb)
{
add(u,v,(ll)1);
add(v,u,(ll)1);
fa[faa]=fbb;
opt++;
}
}
dfs(1,0);
rmq(2*n-1);//4
ll ans=0;
scanf("%d",&q);
while(q--)
{
int u,v,uu,vv;
scanf("%d%d%d%d",&u,&v,&uu,&vv);
ans=cal(get_id(u,v),get_id(uu,vv));
printf("%lld\n",ans);
}
}
return 0;
}