A - How far away ? C- Distance Queries,B - Design the city 图论lca

 

There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.

Input

First line is a single integer T(T<=10), indicating the number of test cases. 
  For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n. 
  Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.

Output

For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.

Sample Input

2
3 2
1 2 10
3 1 15
1 2
2 3

2 2
1 2 100
1 2
2 1

Sample Output

10
25
100
100

 

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>     
#include<algorithm>
#define ll long long
#define hengheng main()
using namespace std;
const int MAX=3e6+5;int T,n,m;
int deep[MAX];int head[MAX],cnt;
int anc[202020][21]; //anc ki代表k的i此幂的祖先 
int dis[202020];// dis i 为i到根节点的距离 
struct node{
    int t,next,len;
}edge[MAX];// 链式前向星存图 
void addedge(int u,int v,int len)// 双向加边 
{
    edge[cnt].t=v;
	edge[cnt].len=len;
	edge[cnt].next=head[u];
	head[u]=cnt++;
}

void dfs(int u,int father)
{
    for(int i=1;i<=20;i++)// 2的幂次增倍 
    {
        anc[u][i]=anc[ anc[u][i-1] ][i-1];
    }
    for(int i=head[u];~i;i=edge[i].next) // 走节点 
    {
        int t=edge[i].t;
        if(t==father)continue; // 
        
        dis[t]=dis[u]+edge[i].len; // 距离 
        deep[t]=deep[u]+1; // 深度 
        anc[t][0]=u; // 父节点循环 
        dfs(t,u); // 往下走 
    }
}
int LCA(int u,int v)
{
    if(deep[u]<deep[v])
	swap(u,v); // 默认u深 
    for(int i=20;i>=0;i--)  
    {
        if(deep[anc[u][i]] >= deep[v])  // 相等记0 不等记 1 
            u=anc[u][i];
    }
    if(u==v)return u; // 如果一个是另一个的祖先节点 直接返回 
    
    for(int i=20;i>=0;i--) 
    {
        if(anc[u][i] != anc[v][i])
        {
            u=anc[u][i];
            v=anc[v][i];
        }
    }
    return anc[u][0];// 最后u v 跑到最近祖先节点的下一个节点; 
}
int hengheng 
{
   	scanf("%d",&T);
	while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(head,-1,sizeof(head)); cnt =0;
        for(int i=1;i<n;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);// 双向加边 
        }
        
        dis[1]=0;
        deep[1]=1;
        anc[1][0]=1;
        dfs(1,1);
        
        for(int i=0;i<m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            int k=LCA(u,v);
            
            int ans=dis[u]+dis[v]-2*dis[k];printf("%d\n",ans);
        }
    }
}

 

C - Distance Queries

Farmer John's cows refused to run in his marathon since he chose a path much too long for their leisurely lifestyle. He therefore wants to find a path of a more reasonable length. The input to this problem consists of the same input as in "Navigation Nightmare",followed by a line containing a single integer K, followed by K "distance queries". Each distance query is a line of input containing two integers, giving the numbers of two farms between which FJ is interested in computing distance (measured in the length of the roads along the path between the two farms). Please answer FJ's distance queries as quickly as possible! 

Input

* Lines 1..1+M: Same format as "Navigation Nightmare" 

* Line 2+M: A single integer, K. 1 <= K <= 10,000 

* Lines 3+M..2+M+K: Each line corresponds to a distance query and contains the indices of two farms. 

Output

* Lines 1..K: For each distance query, output on a single line an integer giving the appropriate distance. 

Sample Input

7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S
3
1 6
1 4
2 6

Sample Output

13
3
36

Hint

Farms 2 and 6 are 20+3+13=36 apart. 

 

思路与lca相同 套用即可

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>     
#include<algorithm>
#define ll long long
#define hengheng main()
using namespace std;
const int MAX=3e6+5;int T,n,m;
int deep[MAX];int head[MAX],cnt;
int anc[202020][21];
int dis[202020];
struct node{
    int t,next,len;
}edge[MAX];
void addedge(int u,int v,int len)
{
    edge[cnt].t=v;
	edge[cnt].len=len;
	edge[cnt].next=head[u];
	head[u]=cnt++;
}

void dfs(int u,int father)
{
    for(int i=1;i<=20;i++)
    {
        anc[u][i]=anc[ anc[u][i-1] ][i-1];
    }
    for(int i=head[u];~i;i=edge[i].next)
    {
        int t=edge[i].t;
        if(t==father)continue;
        
        dis[t]=dis[u]+edge[i].len;
        deep[t]=deep[u]+1;
        anc[t][0]=u;
        dfs(t,u);
    }
}
int LCA(int u,int v)
{
    if(deep[u]<deep[v])
	swap(u,v); // 默认u深 
    for(int i=20;i>=0;i--)  
    {
        if(deep[anc[u][i]] >= deep[v])
            u=anc[u][i];
    }
    if(u==v)return u;
    
    for(int i=20;i>=0;i--) 
    {
        if(anc[u][i] != anc[v][i])
        {
            u=anc[u][i];
            v=anc[v][i];
        }
    }
    return anc[u][0];
}
int hengheng 
{
   	scanf("%d",&T);
	char ch[10];
    {
        scanf("%d",&n); 
        memset(head,-1,sizeof(head)); cnt =0;
        for(int i=0;i<n;i++)
        {
            int u,v,w;
            scanf("%d%d%d%s",&u,&v,&w,ch);
            addedge(u,v,w);
            addedge(v,u,w);
        }
        
        dis[1]=0;
        deep[1]=1;
        anc[1][0]=1;
        dfs(1,1);
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            int k=LCA(u,v);
            
            int ans=dis[u]+dis[v]-2*dis[k];printf("%d\n",ans);
        }
    }
}

 

 

Cerror is the mayor of city HangZhou. As you may know, the traffic system of this city is so terrible, that there are traffic jams everywhere. Now, Cerror finds out that the main reason of them is the poor design of the roads distribution, and he want to change this situation.

In order to achieve this project, he divide the city up to N regions which can be viewed as separate points. He thinks that the best design is the one that connect all region with shortest road, and he is asking you to check some of his designs.

Now, he gives you an acyclic graph representing his road design, you need to find out the shortest path to connect some group of three regions.

 

Input

 

The input contains multiple test cases! In each case, the first line contian a interger N (1 < N < 50000), indicating the number of regions, which are indexed from 0 to N-1. In each of the following N-1 lines, there are three interger Ai, Bi, Li (1 < Li < 100) indicating there's a road with length Li between region Ai and region Bi. Then an interger Q (1 < Q < 70000), the number of group of regions you need to check. Then in each of the following Q lines, there are three interger Xi, Yi, Zi, indicating the indices of the three regions to be checked.

Process to the end of file.

 

Output

 

Q lines for each test case. In each line output an interger indicating the minimum length of path to connect the three regions.

Output a blank line between each test cases.

 

Sample Input

 

4
0 1 1
0 2 1
0 3 1
2
1 2 3
0 1 2
5
0 1 1
0 2 1
1 3 1
1 4 1
2
0 1 2
1 0 3

 

Sample Output

 

3
2

2
2

 

 

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>     
#include<algorithm>
#define ll long long
using namespace std;
const int maxx=2e5+10;
#define hengheng main()
#define mem(a,b) memset(a,b,sizeof(a))
int cnt=0;
int head[maxx],deep[maxx];int dis[maxx]; /// dis i 代表i与根节点距离 
int ans[maxx][21]; /// ans ki  k的i次幂祖先 
// 链式前向星 
struct stu{
	int to,next,len;
}A[maxx];

void addedge(int u,int v,int len)
{
	A[cnt].to=v;
	A[cnt].len=len;
	A[cnt].next=head[u];
	head[u]=cnt++;
}
int lca(int x,int y)
{
	if (deep[x] < deep[y]) swap(x,y);
	for (int i = 20; i >= 0; i--)
		if (deep[ans[x][i]] >= deep[y]) x = ans[x][i];
	if (x == y) return x;
	for (int i = 20; i >= 0; i--)
		if (ans[x][i] != ans[y][i]){
			x = ans[x][i];
			y = ans[y][i];
		}
	return ans[x][0];
	
}

void dfs(int u,int fa,int dep)
{
	ans[u][0] = fa;
	deep[u] = dep;
	for (int i = 1; i < 21; i++)
		ans[u][i] = ans[ans[u][i-1]][i-1];
	for (int i  = head[u]; i != -1; i = A[i].next){
		int t = A[i].to;
		if (fa == t) continue;
			dis[t] = dis[u] + A[i].len;
			dfs(t,u,dep+1);
	}
}
int clac(int x, int y)
{
	return dis[x] + dis[y] - 2*dis[lca(x,y)];
}
int hengheng
{
		int x,y,z;
		int n,m,i;
	 bool flag = 0;
	while(scanf("%d",&n) != EOF)
	{
		if (flag) printf("\n");
		flag = 1;
		mem(head,-1);cnt=0;
		for(i=1;i<n;i++)
		{
			scanf("%d%d%d",&x,&y,&z);
			addedge(x,y,z);
			addedge(y,x,z);
		}
		dfs(0,0,0);
		scanf("%d",&m);
		for(i=0;i<m;i++)
		{
			scanf("%d%d%d",&x,&y,&z);
			int ans = clac(x,y)+clac(y,z)+clac(x,z);
			printf("%d\n",ans/2);
		}
	 }
	
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值