• 「JSOI2013」侦探jyy


    「JSOI2013」侦探jyy

    传送门

    个人感觉我写的复杂度不够优秀啊,但是好像没有别的办法了...

    我们枚举每个点,考虑这个点能不能不发生。

    首先我们从这个点开始,在反图上面 ( ext{BFS}) 只要碰到已经发生的点则这个点必须发生。

    然后我们再考虑是不是能满足题目要求的点都发生,那么我们就把所有之前那次 ( ext{BFS}) 没有访问到的入度为零的点都用来在原图上 ( ext{BFS}) ,如果还是存在一个点不能被满足则这个点也必须发生。

    否则可以不发生。

    复杂度好像是 (O(nm)) 的,但是跑不满所以还是可以过(雾

    #include <cstring>
    #include <cstdio>
    #include <queue>
    #define rg register
    #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
    using namespace std;
    template < class T > inline void read(T& s) {
        s = 0; int f = 0; char c = getchar();
        while ('0' > c || c > '9') f |= c == '-', c = getchar();
        while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
        s = f ? -s : s;
    }
     
    const int _ = 1e3 + 5, __ = 1e5 + 5;
     
    int tot, phead[_], rhead[_]; struct Edge { int v, nxt; } edge[__ << 1];
    inline void Add_edge(int* head, int u, int v) { edge[++tot] = (Edge) { v, head[u] }, head[u] = tot; }
     
    int n, m, k, a[_], ra[_], dgr[_], vis[_];
    queue < int > Q;
     
    inline void bfs(int x) {
        memset(vis + 1, 0, sizeof (int) * n);
        Q.push(x);
        while (!Q.empty()) {
    	    int u = Q.front(); Q.pop(), vis[u] = 1;
    	    for (rg int i = rhead[u]; i; i = edge[i].nxt)
    	        if (!vis[edge[i].v]) Q.push(edge[i].v);
        }
    }
     
    inline bool check(int x) {
        bfs(x);
        for (rg int i = 1; i <= k; ++i) if (vis[a[i]]) return 1;
        for (rg int i = 1; i <= n; ++i) if (!dgr[i] && !vis[i]) Q.push(i);
        while (!Q.empty()) {
        	int u = Q.front(); Q.pop(), vis[u] = 1;
        	for (rg int i = phead[u]; i; i = edge[i].nxt)
    	        if (!vis[edge[i].v]) Q.push(edge[i].v);
        }
        for (rg int i = 1; i <= k; ++i) if (!vis[a[i]]) return 1;
        return 0;
    }
     
    int main() {
    #ifndef ONLINE_JUDGE
        file("cpp");
    #endif
        read(n), read(m), read(k);
        for (rg int u, v, i = 1; i <= m; ++i)
        read(u), read(v), Add_edge(phead, u, v), Add_edge(rhead, v, u), ++dgr[v];
        for (rg int i = 1; i <= k; ++i) read(a[i]), ra[a[i]] = 1;
        for (rg int i = 1; i <= n; ++i) if (ra[i] || check(i)) printf("%d ", i);
        return 0;
    }
    
  • 相关阅读:
    Best code水题之路
    我的CodeF水A题之路
    studing(来自转载)
    BFS
    fibonacci数列(五种)
    Redis阻塞队列原理学习
    the enum hack
    Divide Two Integers
    Surrounded Regions
    Search in Rotated Sorted Array
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/12283623.html
Copyright © 2020-2023  润新知