Codeforces1248F. Catowice City

题意:1e6个人每人有一只猫 每个人认识自己的猫 现给出一些关系表示一个人认识某只猫

   要选出一些人和一些猫 使得每个人都不认识选出来的猫 且人+猫=n

题解:答案肯定是 一个人的集合和一个猫的集合

   那么对于某个人 他要么在这个答案集合中 要么不在 我们考虑第一个人

   先考虑这个人在答案集合中 如果这个人认识某只猫 那么拥有这只猫的主人显然也应该放在答案集合中

   所以不停把人放入队列进来 如果最后这个人的集合没有n个人 则是一种合法的方案

   然后考虑第一个人不在答案集合中 那么逆向思维等于我们选了第一个人的猫 如果某个人认识这只猫

   那么这个人的猫也应该放在猫的集合里 瞎搞搞就完了

#include <bits/stdc++.h>
using namespace std;
 
int n, m, l, r;
vector<int> g[2][1000005];
int que[1000005];
int vis[1000005];
void solve(int typ) {
    for(int i = 1; i <= n; i++) vis[i] = 0;
    l = 1, r = 0;
    que[++r] = 1; vis[1] = 1;
 
    while(l <= r) {
        int u = que[l]; l++;
        for(int i = 0; i < g[typ][u].size(); i++) {
            int v = g[typ][u][i];
            if(!vis[v]) {
                vis[v] = 1;
                que[++r] = v;
            }
        }
    }
}
 
int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++) g[0][i].clear(), g[1][i].clear();
        for(int i = 1; i <= m; i++) {
            int x, y;
            scanf("%d%d", &x, &y);
            if(x == y) continue;
            g[0][x].push_back(y);
            g[1][y].push_back(x);
        }
 
        solve(0);
        if(r != n) {
            puts("Yes");
            printf("%d %d\n", r, n - r);
            for(int i = 1; i <= r; i++) printf("%d ", que[i]);
            puts("");
            for(int i = 1; i <= n; i++) if(!vis[i]) printf("%d ", i);
            puts("");
            continue;
        }
        solve(1);
        if(r != n) {
            puts("Yes");
            printf("%d %d\n", n - r, r);
            for(int i = 1; i <= n; i++) if(!vis[i]) printf("%d ", i);
            puts("");
            for(int i = 1; i <= r; i++) printf("%d ", que[i]);
            puts("");
            continue;
        }
        puts("No");
    }
    return 0;
}
View Code

 

   

posted @ 2019-10-24 17:03  lwqq3  阅读(204)  评论(0编辑  收藏  举报