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

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 RRand 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

题目来源

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

题意:

给出一个n*m的方阵,已知每个方格与下方和右方的方格之间设置一面墙的价格,问如何花费最少的费用建立足够的墙使得所有的方块都有且只有一条路可以到达。

然后提出q个询问,问每个询问的两个点之间的路程

思路:

把每个方格都看成一个点,而这两个方格之间的墙就是这两个点之间的一条边。首先把整个上的墙都看成是建立的状态,那么想要让所有的点之间有且仅有一条条边可以到达,就要让所有的点之间的生成树的边代表的墙都拆去。而为了满足花费代价最小的目的,我们拆去的边就需要是最大的,因此就是在所有的点之间跑一条最大生成树。

完成建树之后,只需要应用LCA来求两点之间的距离就可以了。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
typedef int Int;
#define int long long
#define endl '\n'
#define sc(x) scanf("%lld",&x)
#define H 505
using namespace std;
const int size=505;
const int maxn=size*size+size;
struct edge{
	int u,v,w;
	edge(){}
	edge(int _u,int _v,int _w):u(_u),v(_v),w(_w){}
	friend bool operator<(edge a,edge b)
	{
		return a.w<b.w;
	}
};
inline int Hash(int x,int y)
{
	return x*H+y;
}
int cnt;
int sum_point;
int fa[maxn];
priority_queue<edge> q;
vector<int> G[maxn];
void init()
{
	while(!q.empty()) q.pop();
	for(int i=Hash(1,1);i<=maxn;i++)
	{
		fa[i]=i;
	}
	cnt=0;
}
int find(int x)
{
	return x==fa[x]?x:fa[x]=find(fa[x]);
}
int merge(int x,int y)
{
	int fx=find(x),fy=find(y);
	if(fx==fy) return 0;
	fa[fx]=fy;
	return 1;
}
inline void link(int u,int v)
{
	G[u].push_back(v);
	G[v].push_back(u);
}
void kruskal()
{
	while(!q.empty())
	{
		edge E=q.top();
		q.pop();
		if(merge(E.u,E.v))
		{
			link(E.u,E.v);
			if(++cnt==sum_point-1)
			{
				break;
			}
		}
	}
	return ;
}
int dep[maxn],pa[maxn][20];
void dfs(int u,int F,int d)
{
	dep[u]=d;
	if(u==Hash(1,1))
	{
		for(int i=0;i<20;i++) pa[u][i]=1;
	}
	else
	{
		pa[u][0]=F;
		for(int i=1;i<20;i++)
		{
			pa[u][i]=pa[pa[u][i-1]][i-1];
		}
	}
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i];
		if(v==F) continue;
		dfs(v,u,d+1);
	}
}
int Jump(int u,int d)
{
	for(int j=19;j>=0;j--)
	{
		if((1<<j)&d)
		{
			u=pa[u][j];
		}
	}
	return u;
}
int lca(int u,int v)
{
	if(dep[u]<dep[v]) swap(u,v);
	u=Jump(u,dep[u]-dep[v]);
	if(u==v) return u;
	for(int i=19;i>=0;i--)
	{
		if(pa[u][i]!=pa[v][i])
		{
			u=pa[u][i];
			v=pa[v][i];
		}
	}
	return pa[u][0];
}
Int main()
{
	int n,m;
	while(~scanf("%lld%lld",&n,&m))
	{
		sum_point=n*m;
		init();
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				char D[5],R[5];
				int d,r;
				scanf("%s%lld%s%lld",D,&d,R,&r);
				if(D[0]=='D')
				{
					q.push(edge(Hash(i,j),Hash(i+1,j),d));
				}
				if(R[0]=='R')
				{
					q.push(edge(Hash(i,j),Hash(i,j+1),r));
				}
			}
		}
		kruskal();
		int q;
		scanf("%lld",&q);
		dfs(Hash(1,1),0,0);
		while(q--)
		{
			int x1,x2,y1,y2;
			scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
			printf("%lld\n",dep[Hash(x1,y1)]+dep[Hash(x2,y2)]-2*dep[lca(Hash(x1,y1),Hash(x2,y2))]);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/baiyifeifei/article/details/82590173