[BZOJ]4151: [AMPPZ2014]The Cave

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 ,也就是dist(1,ai)+dist(1,bi)>di,设 LCA(ai,bi)=x ,那么我们至少需要到达 x 的第ddist(ai,bi)2个祖先(这个显然吧),所以答案点到1号店的距离为 dist(1,x)ddist(ai,bi)2 ,化简式子后得到 dist(1,ai)+dist(1,bi)di2 ,别忘了我们是在考虑1号点不符合条件的情况,所以还有一个0。之后的应该很好懂吧,在此我就不赘述了。

代码:

#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);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值