Description
给定一棵有n个节点的树,相邻两点之间的距离为1。
请找到一个点x,使其满足所有m条限制,其中第i条限制为dist(x,a[i])+dist(x,b[i])<=d[i]。
题解:
%%%Claris。Claris的题解中说,1号点到答案点的距离为
max(0,dist(1,ai)+dist(1,bi)−di2)
,一开始不懂,后来看了另外一篇题解之后明白了:假设我们现在在1(根),假如不满足某一个限制
i
,也就是
代码:
#include<bits/stdc++.h>
using namespace std;
const int Maxn=300010;
struct Edge{int next,y;}e[Maxn*2];
int last[Maxn],len;
void ins(int x,int y)
{
int t=++len;
e[t].y=y;e[t].next=last[x];last[x]=t;
}
int n,m,a[Maxn],b[Maxn],d[Maxn],mx,mn,w,dis[4][Maxn],o;
void dfs(int x,int fa,int t,int o)
{
dis[o][x]=t;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==fa)continue;
dfs(y,x,t+1,o);
}
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
memset(last,0,sizeof(last));len=0;
mx=-1,mn=(1<<30);
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ins(x,y);ins(y,x);
}
dfs(1,0,0,0);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a[i],&b[i],&d[i]);
o=max(0,dis[0][a[i]]+dis[0][b[i]]-d[i]);
if(o>mx)mx=o,w=i;
}
dfs(a[w],0,0,1);dfs(b[w],0,0,2);o=d[w];w=-1;
for(int i=1;i<=n;i++)
if(dis[1][i]+dis[2][i]<=o){if(dis[0][i]<mn)mn=dis[0][i],w=i;}
if(w==-1){puts("NIE");continue;}
dfs(w,0,0,3);bool no=false;
for(int i=1;i<=m;i++)if(dis[3][a[i]]+dis[3][b[i]]>d[i]){no=true;break;}
if(no)puts("NIE");else printf("TAK %d\n",w);
}
}