Codeforces 1304E. 1-Trees and Queries

简述题意,给你一课最小支撑树,对每个询问,在原有的路径上增加x-y,问a-b是否有路径长度为k的路,每条路每个点可以重复使用

由于是最小支撑树,我们可以用LCA来快速判断每个点之间的距离,那么现在就要判断情况,假设从原有的路上,a-b的距离为d,d=k时显然成立,当d<k时,若(d-k)%2=0也成立,因为若其是2的倍数,他可以轮流进入b与b的前驱,最后停在b上,那么我们如何判断新加的边的,距离的判定和前者一样,但是距离的大小变化了,设(x,y)表示x到y的最短路径,则从a到b就有三种情况

1.(a,b) 该情况已经讨论过

2.(a,x)+(b,y)+1,意思从a到x,x到y的路径长度为1,y再到b

3.(a,y)+(b,x)+1,同理

三种情况下的距离判断都一样,具体上代码看一下就懂了

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) ((x)&(-x))
typedef long long LL;

const int maxm = 1e5+5;
struct Node {
    int v, nex;
} edges[maxm<<1];

int head[maxm<<1], edgecnt, grand[maxm][21], depth[maxm], limit;

void addedge(int u, int v) {
    edges[++edgecnt] = {v, head[u]};
    head[u] = edgecnt;
}

void dfs(int u, int fa) {
    depth[u] = depth[fa] + 1;
    grand[u][0] = fa;
    for(int i = 1; i <= limit; ++i) grand[u][i] = grand[grand[u][i-1]][i-1];
    for(int i = head[u]; i; i = edges[i].nex) {
        int v = edges[i].v;
        if(v != fa) dfs(v, u);
    }
}

int lca(int a, int b) {
    if(a == b) return a;
    if(depth[a] > depth[b]) swap(a, b);
    for(int i = limit; i >= 0; i--) 
        if(depth[a] <= depth[b] - (1<<i)) b = grand[b][i];
    if(a == b) return a;
    for(int i = limit; i >= 0; --i) {
        if(grand[a][i] == grand[b][i])
            continue;
        else {
            a = grand[a][i], b = grand[b][i];
        }
    }
    return grand[a][0];
}

int getdist(int a, int b) {
    int c = lca(a, b);
    return depth[a] + depth[b] - 2*depth[c];
}


void run_case() {
    int n; cin >> n;
    limit = floor(log(n+0.0) / log(2.0)) + 1;
    int u, v;
    for(int i = 0; i < n-1; ++i) {
        cin >> u >> v;
        addedge(u, v), addedge(v, u);
    }
    dfs(1, 0);
    int q; cin >> q;
    int a, b, x, y, k;
    while(q--) {
        cin >> x >> y >> a >> b >> k;
        int dist = getdist(a, b);
        bool flag = false;
        if(dist <= k && (k-dist)%2==0) flag = true;
        dist = getdist(a, x) + getdist(b, y) + 1;
        if(dist <= k && (k-dist)%2==0) flag = true;
        dist = getdist(a, y) + getdist(b, x) + 1;
        if(dist <= k && (k-dist)%2==0) flag = true;
        if(flag) cout << "YES\n";
        else cout << "NO\n";
    }
}
 
int main() {
    ios::sync_with_stdio(false), cin.tie(0);
    //cout.setf(ios_base::showpoint);cout.precision(10);
    //int t; cin >> t;
    //while(t--)
    run_case();
    cout.flush();
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/GRedComeT/p/12316678.html