codeforces gym102411 Equidistant(圖論+亂搞)


傳送門

題意:給定一顆n個結點的樹,樹上有m個結點有隊伍,求存不存在一個點s,到所有m個隊伍所在結點的距離相等,如果存在輸出可能一個的s。

分析:假設存在s,那么可以改變樹的順序,使得s是所有隊伍結點的祖先,此時s的所有祖先都是滿足的s,令所有滿足條件的s中里隊伍結點最近的s為ms。dfs可以求得隊伍結點中的直徑,直徑端點為st,ed。如果直徑是奇數,肯定不存在,因為已知不存在與st,ed距離相等的點。如果直徑是偶數,令直徑的中點為c,因為假設s存在,所以st,ed的中點一定是所有點的中點,而且此時c一定是ms,此時驗證c是否滿足條件即可。dfs驗證c到所有隊伍結點的距離是否相等,如果滿足條件,輸出c。

需要注意的是,當只有一個隊伍節點時,st=ed,兩遍dfs找直徑時需要把直徑長度置為0,否則無法找到ed。

代碼:

#include <bits/stdc++.h>
#define mp make_pair
#define debug(x) cout << #x << ": " << x << endl
#define pb push_back
typedef long long LL;
const int maxn = 3e5 + 10;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
using namespace std;
int n, m, len, u, v, f[maxn], path[maxn], st, ed, dis[maxn], c;
vector<int> g[maxn];
void dfs(int now, int pre,int steps) {
    if (f[now]) {
        if (steps >= len) {
            st = now;
            len = steps;
        }
    }
    for (int i = 0; i < g[now].size(); ++i) {
        int to = g[now][i];
        if (to == pre)
            continue;
        dfs(to, now, steps + 1);
    }
}
void _dfs(int now, int pre, int steps) {
    if (f[now])
        dis[now] = steps;
    for (int i = 0; i < g[now].size(); ++i) {
        int to = g[now][i];
        if (to == pre)
            continue;
        _dfs(to, now, steps + 1);
    }
}
void __dfs(int now, int pre, int steps) {
    if (f[now]) {
        if (steps >= len) {
            ed = now;
            len = steps;
        }
    }
    for (int i = 0; i < g[now].size(); ++i) {
        int to = g[now][i];
        if (to == pre)
            continue;
        path[to] = now;
        __dfs(to, now, steps + 1);
    }
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m;
    st = ed = len = 0;
    for (int i = 1; i < n; ++i) {
        cin >> u >> v;
        g[u].pb(v);
        g[v].pb(u);
    }
    for (int i = 0; i < m; ++i) {
        cin >> u;
        f[u] = 1;
    }
    dfs(1, 0, 0);
    len = 0;
    __dfs(st, 0, 0);
    if (len & 1) {
        cout << "NO\n";
    }
    else {
        int temp = ed;
        int cnt = 0;
        while (cnt != len / 2) {
            temp = path[temp];
            ++cnt;
        }
        c = temp;
        _dfs(c,0,0);
        int x = -1;
        for (int i = 1; i <= n; ++i) {
            if (f[i]) {
                if (x == -1)
                    x = dis[i];
                else if (dis[i] != x) {
                    cout << "NO\n";
                    exit(0);
                }
            }
        }
        cout << "YES\n" << c;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM