• bzoj4151 [AMPPZ2014]The Cave


    Description

    给定一棵有 (n) 个节点的树,相邻两点之间的距离为 (1)

    请找到一个点 (x) ,使其满足所有 (m) 条限制,其中第i条限制为 (dist(x,a[i])+dist(x,b[i])le d[i])

    Input

    第一行包含一个正整数 (t(1 le t le 1000)) ,表示数据组数。

    对于每组数据,第一行包含两个正整数 (n,m(2le n,mle 300000)) ,表示点数、限制数。

    接下来 (n-1) 行,每行两个正整数 (x,y(1le x,yle n)) ,表示树上的一条边。

    接下来 (m) 行,每行三个正整数 $a[i],b[i],d[i] (1le a[i],b[i]le n,1le d[i]le 600000) $ ,描述一条限制。

    输入数据保证所有 (n) 之和不超过 (300000) ,所有 (m) 之和也不超过 (300000)

    Output

    输出 (t) 行。第 (i) 行输出第 (i) 组数据的答案,如果无解输出 (mathrm{NIE}) ,否则输出 (mathrm{TAK})

    然后输出 (x) ,如有多组解,输出任意一组。

    Sample

    Sample Input

    2
    5 3
    1 2
    2 3
    2 4
    3 5
    1 4 2
    5 5 5
    3 2 1
    3 2
    1 2
    2 3
    1 1 2
    3 3 1
    

    Sample Output

    TAK 2
    NIE
    

    Solution

    (mathrm{Azrael \_ Death}) 巨巨的强力推荐下做了此题。

    好题,完全没想到正解。

    可参考另一篇写得很清楚的博客:BZOJ4151【AMPPZ2014】The Cave <树相关>

    #include<bits/stdc++.h>
    using namespace std;
    
    #define N 300001
    #define rep(i, a, b) for (int i = a; i <= b; i++)
    
    inline int read() {
    	int x = 0, flag = 1; char ch = getchar(); while (!isdigit(ch)) { if (!(ch ^ '-')) flag = -1; ch = getchar(); }
    	while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * flag;
    }
    
    int n, m, head[N], tot, dis[4][N], a[N], b[N], d[N];
    struct edge { int v, next; }e[N << 1];
    inline void add(int u, int v) { e[++tot].v = v, e[tot].next = head[u], head[u] = tot; }
    
    void dfs(int u, int fa, int dep, int t) {
    	dis[t][u] = dep;
    	for (int i = head[u]; i; i = e[i].next) if (e[i].v != fa) dfs(e[i].v, u, dep + 1, t);
    }
    
    int main() {
    	for (int T = read(); T--;) {
    		n = read(), m = read(); memset(head, 0, sizeof head), tot = 0;
    		rep(i, 2, n) { int u = read(), v = read(); add(u, v), add(v, u); }
    		dfs(1, 0, 0, 0);
    		int mx = -1, mn = 0x7fffffff, p;
    		rep(i, 1, m) {
    			a[i] = read(), b[i] = read(), d[i] = read();
    			int t = max(0, dis[0][a[i]] + dis[0][b[i]] - d[i]);
    			if (t > mx) mx = t, p = i;
    		}
    		dfs(a[p], 0, 0, 1), dfs(b[p], 0, 0, 2);
    		int tmp = d[p]; p = 0;
    		rep(i, 1, n) if (dis[1][i] + dis[2][i] <= tmp && dis[0][i] < mn) mn = dis[0][i], p = i;
    		if (!p) { puts("NIE"); continue; }
    		dfs(p, 0, 0, 3);
    		bool flag = 1; rep(i, 1, m) if (dis[3][a[i]] + dis[3][b[i]] > d[i]) { flag = 0; break; }
    		if (flag) printf("TAK %d
    ", p); else puts("NIE");
    	}
    	return 0;
    }
    
  • 相关阅读:
    动态字节码技术Javassist
    自己实现简单版的注解Mybatis
    AOP实现事务和记录日志
    自己实现简单版SpringMVC
    静态变量
    docker安装nginx , 安装mysql5.6,安装redis3.2
    Worker Thread模式
    linux 安装jdk
    dockfile构建自己的tomcat
    docker使用2
  • 原文地址:https://www.cnblogs.com/aziint/p/8493917.html
Copyright © 2020-2023  润新知