ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer(最大生成树+lca)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37943488/article/details/82584722

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.

扫描二维码关注公众号,回复: 3206195 查看本文章

样例输入复制

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

题目来源

ACM-ICPC 2018 徐州赛区网络预赛

题意:一个迷宫,两个格子之间可能有墙也可能没墙,要求将两个人分别放在迷宫的不同的格子时,无论放在哪,他们之间只有一条路能走,而且墙的花费要最少,q次询问问他们之间的距离。

放在哪里都只有一条路可走要想到树,花费最小的话就等于对迷宫求一次最大生成树,那么剩下的边就是墙,求两人的最短距离就是求生成树上的lca

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=250010;
const int maxm=500010;
struct LDJ
{
    int from;
    int to;
    int len;
}node[maxm];
struct Node
{
    int to;
    int len;
    int next;
}edge[maxm];
int n,m;
int node_cnt;
int cnt;
int head[maxn];
int tree[maxn];
int in[maxn];
int dis[maxn];
int par[250010][50];
int depth[250010];
void init()
{
    cnt=0;
    memset(head,-1,sizeof(head));
    memset(in,0,sizeof(in));
    memset(depth,-1,sizeof(depth));
    for(int i=0;i<maxn;i++)
    {
        tree[i]=i;
    }
    return;
}
void add(int u,int v,int len)
{
    edge[cnt].to=v;
    edge[cnt].len=len;
    edge[cnt].next=head[u];
    head[u]=cnt++;
    return;
}
bool cmp(LDJ a,LDJ b)
{
    return a.len>b.len;
}
int find(int x)
{
    return tree[x]==x?x:tree[x]=find(tree[x]);
}
void merge(int u,int v)
{
    int x=find(u);
    int y=find(v);
    if(x!=y)
    {
        tree[x]=y;
    }
    return;
}
void dfs(int node,int fa,int dep)
{
	depth[node]=dep;
	par[node][0]=fa;
	for(int i=head[node];~i;i=edge[i].next)
	{
		int v=edge[i].to;
		if(depth[v]==-1)
		{
            dis[v]=dis[node]+1;
			dfs(v,node,dep+1);
		}
	}
	return;
}
void lca_init()
{
	for(int j=1;(1<<j)<=n*m;j++)
	{
		for(int i=1;i<=n*m;i++)
		{
			par[i][j]=par[par[i][j-1]][j-1];
		}
	}
	return;
}
int lca(int x,int y)
{
	if(depth[x]<depth[y])
	{
		swap(x,y);
	}
	int sub=depth[x]-depth[y];
	for(int i=0;(1<<i)<=sub;i++)
	{
		if((1<<i)&sub)
		{
			x=par[x][i];
		}
	}
	if(x==y) return x;
	for(int i=20;i>=0;i--)
	{
		if(par[x][i]!=par[y][i])
		{
			x=par[x][i];
			y=par[y][i];
		}
	}
	return par[x][0];
}
int getIndex(int x,int y)
{
    return (x-1)*m+y;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            int node_index=getIndex(i,j);
            char ch1,ch2;
            int a,b;
            cin>>ch1>>a>>ch2>>b;
            if(ch1=='D')
            {
                int x=getIndex(i+1,j);
                node[node_cnt].from=node_index;
                node[node_cnt].to=x;
                node[node_cnt++].len=a;
            }
            if(ch2=='R')
            {
                int x=getIndex(i,j+1);
                node[node_cnt].from=node_index;
                node[node_cnt].to=x;
                node[node_cnt++].len=b;
            }

        }
    }
    sort(node,node+node_cnt,cmp);
    init();
    int sum=0;
    for(int i=0;i<node_cnt;i++)
    {
        int u=node[i].from;
        int v=node[i].to;
        if(find(u)!=find(v))
        {
            merge(u,v);
            add(u,v,node[i].len);
            add(v,u,node[i].len);
            in[v]++;
            sum++;
            if(sum==n*m-1) break;
        }
    }
    int root;
    for(int i=1;i<=n*m;i++)
    {
        if(!in[i])
        {
            root=i;
            break;
        }
    }
    dis[root]=0;
    dfs(root,-1,1);
    lca_init();
    int q;
    scanf("%d",&q);
    for(int i=0;i<q;i++)
    {
        int a,b;
        int x,y;
        scanf("%d%d%d%d",&a,&b,&x,&y);
        int nodea=getIndex(a,b);
        int nodeb=getIndex(x,y);
        cout<<dis[nodea]+dis[nodeb]-2*dis[lca(nodea,nodeb)]<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37943488/article/details/82584722