[bzoj4151][AMPPZ2014]The Cave
来自FallDream的博客,未经允许,请勿转载,谢谢。
给定一棵有n个节点的树,相邻两点之间的距离为1。
请找到一个点x,使其满足所有m条限制,其中第i条限制为dist(x,a[i])+dist(x,b[i])<=d[i]。
n<=300000,m<=300000
一个点如果满足题意,那么他和点1的距离至少为$max(0,\frac{ai+bi-di}{2})$
找出最大的那个点。如果有解,那么那个点肯定可以。暴力判断行不行就可以了。
#include<iostream> #include<cstdio> #define MN 300000 #define getchar() (*S++) char B[1<<26],*S=B; using namespace std; inline int read() { int x = 0; char ch = getchar(); while(ch < '0' || ch > '9') ch = getchar(); while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x; } int head[MN+5],n,m,cnt=0,dep[MN+5],a[MN+5],fa[MN+5],b[MN+5],d[MN+5]; struct edge{int to,next;}e[MN*2+5]; inline void ins(int f,int t) { e[++cnt]=(edge){t,head[f]};head[f]=cnt; e[++cnt]=(edge){f,head[t]};head[t]=cnt; } void Dfs(int x,int f) { fa[x]=f; for(int i=head[x];i;i=e[i].next) if(e[i].to!=f) dep[e[i].to]=dep[x]+1,Dfs(e[i].to,x); } int main() { fread(B,1,1<<26,stdin); for(int T=read();T;--T) { n=read();m=read();cnt=0; for(register int i=1;i<=n;++i) head[i]=0; for(register int i=1;i<n;++i) ins(read(),read()); dep[1]=0;Dfs(1,0);int mx=0,From=1; for(register int i=1;i<=m;++i) a[i]=read(),b[i]=read(),d[i]=read(), (dep[a[i]]+dep[b[i]]-d[i]+1)/2>mx?(mx=(dep[a[i]]+dep[b[i]]-d[i]+1)/2,From=i):0; for(From=a[From];dep[From]>mx;From=fa[From]); dep[From]=0;Dfs(From,0);bool flag=1; for(register int i=1;i<=m;++i) if(dep[a[i]]+dep[b[i]]>d[i]) {flag=0;break;} if(flag) printf("TAK %d\n",From); else puts("NIE"); } return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream