您的位置:首页 > 产品设计 > UI/UE

UESTC - 92 Journey(LCA)1012四川省赛

2015-10-12 11:27 429 查看
题目链接:点击打开链接

题意:给你一棵n个结点的生成树,在任选两个点建立一条边,然后有q个询问,求加上这条边后两点的距离减少了多少,如果没有减少或者是增加了,那么输出0;

分析:既然是一棵树,那么我们就可以在树上进行操作,第一想法就是LCA,假设在u和v两点间建立的边,求x到y 的距离,原来的就是dis[x]+dis[y]-2*dis[lca(x,y)]

经过这条边的距离就是xu+uv+vy或者xv+uv+uy,取两者中最小的,然后和原来的距离做差就可以了。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <ctype.h>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define eps 1e-8
#define INF 0x7fffffff
#define maxn 100005
#define PI acos(-1.0)
using namespace std;
typedef long long LL;
const int N = 100005;
int n , m , pre
, mcnt;
bool vis
;
struct edge
{
int x , next ,flag ;
} e[N << 1];

int dep
, f[18]
, Lev , s
,dis
;///1<<16 < N, f[j][i] 表示i的第2^j个祖先
int shang
,xia
;

void dfs(int u ,int fa,int c,int d)///也可以用bfs,但bfs不能统计节点孩子个数
{
dep[u] = d + 1;
f[0][u] = fa ;
dis[u]=c;
for (int i = pre[u] ; ~i ; i = e[i].next)
{
int y = e[i].x;
if(y==fa)
continue;
dfs(y,u,c+e[i].flag,d+1);
}
}

int LCA(int x , int y)
{
if (dep[x] > dep[y]) swap(x , y);
for (int i = Lev ; i >= 0 ; -- i)///找y的第dep[y] - dep[x]个祖先
if (dep[y] - dep[x] >> i & 1)
y = f[i][y];
if (x == y) return y;
for (int i = Lev ; i >= 0 ; -- i)
if (f[i][x] != f[i][y])
x = f[i][x] , y = f[i][y];
return f[0][x];
}

void init()
{
memset(pre , -1 , sizeof(pre));
memset(dis,0,sizeof dis);
mcnt = 0;
}
void addedge(int x,int y ,int f)
{
e[mcnt].x = y,
e[mcnt].next = pre[x],
e[mcnt].flag = f;
pre[x] = mcnt ++;
}
void work(int n,int m)
{
int i , j , x , y , z,anc;
init();
for (i = 1 ; i < n ; ++ i)
{
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z);
addedge(y,x,z);
}
dfs(1 ,-1, 0,0);
for (j = 1 ; 1 << j < n ; ++ j)///ST算法求祖先
for (i = 1 ; i <= n ; ++ i)
f[j][i] = f[j - 1][f[j - 1][i]];
Lev = j - 1;
int u,v,l;
scanf("%d%d%d",&u,&v,&l);
while(m--)
{
scanf("%d%d",&x,&y);
int xu,uv,vy,xv,uy,xy;
xu=dis[x]+dis[u]-2*dis[LCA(x,u)];
vy=dis[v]+dis[y]-2*dis[LCA(v,y)];
xv=dis[x]+dis[v]-2*dis[LCA(x,v)];
uy=dis[u]+dis[y]-2*dis[LCA(u,y)];
xy=dis[x]+dis[y]-2*dis[LCA(x,y)];
int d1,d2,d3;
d1=xu+l+vy;
d2=xv+l+uy;
d3=min(d1,d2);
int ans=max(0,(xy-d3));
printf("%d\n",ans);
}
}

int main()
{
int t,cnt=1;
cin>>t;
while(t--)
{
printf("Case #%d:\n",cnt++);
scanf("%d%d",&n,&m);
work(n,m);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: