1 条题解
-
1
题意:
给一棵个节点的树和条限制,每条限制形如,其中表示到经过的边的个数。问图中是否存在满足所有限制,有的话输出任意一个合法解,否则输出无解。 设为根。 依次遍历每条限制,如果均在的子树中且限制不成立,那么向这个点的到的这条链上向子树方向移动,直至满足限制,如果移动到处仍不满足限制则说明无解。
标程
#include <cstdio> #include <cstring> #include <iostream> #include <vector> #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define ForkD(i,k,n) for(int i=n;i>=k;i--) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Lson (o<<1) #define Rson ((o<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,0x3f,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define MEMx(a,b) memset(a,b,sizeof(a)); #define INF (0x3f3f3f3f) #define F (1000000007) #define pb push_back #define mp make_pair #define fi first #define se second #define SI(a) ((a).size()) #define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans); #define PRi(a,n) For(i,n-1) std::cout<<a[i]<<' '; std::cout<<a[n]<<std::endl; #define PRi2D(a,n,m) For(i,n) { \ For(j,m-1) std::cout<<a[i][j]<<' ';\ std::cout<<a[i][m]<<std::endl; \ } #define ALL(x) (x).begin(),(x).end() typedef long long ll; typedef long double ld; typedef unsigned long long ull; ll mul(ll a,ll b){return (a*b)%F;} ll add(ll a,ll b){return (a+b)%F;} ll sub(ll a,ll b){return ((a-b)%F+F)%F;} void upd(ll &a,ll b){a=(a%F+b%F)%F;} inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN (310000) int n,m; int t_cnt=0,dfn[MAXN],dep[MAXN],r[MAXN]; ll deep[MAXN]; struct edge{ int v,w; }; std::vector<edge> e[MAXN]; int fa[MAXN][21]; void dfs(int x,int fa,ll d=0,ll d2=0) { ::fa[x][0]=fa; For(i,20) ::fa[x][i]=::fa[::fa[x][i-1]][i-1]; deep[x]=d;dep[x]=d2; dfn[x]=++t_cnt; for(int i=0;i<SI(e[x]);i++) { edge node = e[x][i]; if (node.v!=fa) { dfs(node.v,x,d+node.w,d2+1); } } r[x]=t_cnt; } int lca(int x,int y) { if (dep[x]<dep[y]) std::swap(x,y); RepD(i,20) if (dep[fa[x][i]]>=dep[y]) { x=fa[x][i]; } RepD(i,20) if (fa[x][i]!=fa[y][i]) { x=fa[x][i],y=fa[y][i]; } if (x!=y) x=fa[x][0],y=fa[y][0]; return x; } ll dis(int x,int y) { return deep[x]+deep[y]-deep[lca(x,y)]*2; } int x[MAXN],y[MAXN],d[MAXN]; bool check(int root) { For(i,m) if (dis(x[i],root)+ dis(y[i],root)>d[i]) return 0; return 1; } bool inside(int a,int b) { return dfn[b]<=dfn[a] &&dfn[a]<=r[b] ; } int main() { // freopen("bzoj4151.in","r",stdin); int t=read(); while(t--) { std::cin>>n>>m; For(i,n) Rep(j,21) fa[i][j]=0; For(i,n) e[i].clear(); For(i,n-1) { int u=read(),v=read(),w=1; e[u].pb({v,w}); e[v].pb({u,w}); } MEM(dfn) t_cnt=0; dfs(1,-1,0,1); int root=1; For(i,m) { x[i]=read(),y[i]=read(),d[i]=read(); if (!(inside(x[i],root) && inside(y[i],root))) continue; while (dis(x[i],root) + dis(y[i],root)>d[i] && inside(x[i],root) &&inside(y[i],root) ) { bool fl=0; Rep(j,SI(e[root])) { edge v=e[root][j]; if (inside(x[i],v.v) &&inside(y[i],v.v) && fa[v.v][0]==root ){ root=v.v;fl=1;break; } } if (!fl) { break; } } } if (check(root)) { printf("TAK %d\n",root); } else { puts("NIE"); } } return 0; }
- 1
信息
- ID
- 715
- 时间
- 1000ms
- 内存
- 10MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 0
- 上传者