Gym - 101615D Rainbow Roads 分析+递归标记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiang_6/article/details/88687010

题意:给一棵n个结点的树,每条边都有一种颜色,要求找出所有的good点,g点定义:从这个点出发,到其他任意结点的简单路径(最短路径),相邻的两条边颜色都不同

思路:对于某个结点O,跟他相连的结点连的边是同种颜色的话,那从这个O点往这个有重复颜色的结点遍历的时候,能遍历到的点都是不合法的,因为他们以这个O点为中心有两条相邻同颜色的边,

我用ER函数遍历不合法的子树,如果在子树中又发现了相邻同色的边,那所有图中就不包含g点了

然后我继续用solve()函数处理其他没访问的点,

//#include<bits/stdc++.h>

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<set>


using namespace std;
typedef long long ll;
typedef pair<int, int> P;

const int maxn = 5e4 + 7;
const int maxd = 1e9 + 7;

const ll mod = 998244353;
const int INF = 0x7f7f7f7f;

int n;

struct node {
    int v, c;
};
vector<node> vec[maxn];
set<int> st[maxn];
set<int> er[maxn];

int vis[maxn];
bool flag = true;

void init() {
    for(int i = 1; i <= n; ++i) {
        vec[i].clear();
        st[i].clear();
        vis[i] = 0;
    }
    flag = true;
}

void print1() {
    printf("%d\n", n);
    for(int i = 1; i <= n; ++i) {
        printf("%d\n", i);
    }
}

bool ER(int id, int f, int c) {
    if(vis[id] == 1) return false;
    vis[id] = 1;
    for(auto i : vec[id]) {
        if(i.v == f) continue;
        if(i.c == c) return true;
        if(ER(i.v, id, i.c)) return true;
    }
    return false;
}
void solve(int id) {
    for(auto i : er[id]) {
        for(auto j : vec[id]) {
            if(j.c == i) {
                if(ER(j.v, id, i)) {
                    printf("0\n");
                    flag = false;
                    return;
                }
            }
        }
    }
    vis[id] = 2;
    for(auto i : vec[id]) {
        if(!vis[i.v]) {
            solve(i.v);
        }
    }
}
void work() {
    vector<int> ans;
    for(int i = 1; i <= n; ++i) {
        if(vis[i] == 2) ans.push_back(i);
    }
    printf("%d\n", ans.size());
    for(auto i : ans) {
        printf("%d\n", i);
    }
}
int main() {
    scanf("%d", &n);
    init();
    for(int i = 1; i < n; ++i) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        vec[a].push_back(node{b, c});
        vec[b].push_back(node{a, c});

        if(st[a].count(c)) er[a].insert(c);
        else st[a].insert(c);
        if(st[b].count(c)) er[b].insert(c);
        else st[b].insert(c);
    }
    int x = -1;
    for(int i = 1; i <= n; ++i) {
        if(er[i].size()) {
            x = i;
            break;
        }
    }
//    cout << x << " =++= ==++ " << endl;
    if(x == -1) {
        print1();
    }
    else {
        solve(x);
        if(flag) {
            work();
        }
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiang_6/article/details/88687010