[BZOJ]4151: [AMPPZ2014]The Cave

来源:互联网 发布:英雄联盟韩服数据库 编辑:程序博客网 时间:2024/05/18 00:21

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);    }}
原创粉丝点击