CodeForces770C【强连通分量+DFS序】

思路:
显然按照他的意思建图肯定不行。
对于u所需要先解决的v[], 建边 u -> v[], 然后就是判断一下每个main 课程是否在一个环里,或者是不是他需要先修的课程在环里,这样子就不满足。
然后我就很爆炸,窝很蠢地想到了Tarjan,然后就处理了一下那些强连通分量,然后就是用来判断是不是在环里,不满足。
然后就是对每个main 课程 DFS搜,然后就好啦,然后智障的窝第一次发现这个拓扑排序的逆序竟然是DFS序。。。
因为菜啊!!不会一次DFS就能判断= =、就瞄了瞄题解。。我就不多bb了…思路基本一样。。。但是人家的写法。。(窝看到的时候内心是崩溃的)

void dfs(int u) {
    if (color[u] == 0) {
        color[u] = 1;
        for (int to: g[u])
            dfs(to);
        color[u] = 2;
        ord.push_back(u);
    } else if (color[u] == 1)
        cycle = true;
}

然后我的搓代码。。(其实单组案例可以去掉那些没必要的初化)

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

typedef pair<int,int> PII;
typedef long long LL;

#define mem(a, b) memset(a, b, sizeof(a))
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1

const double eps = 1e-9;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;

const int Maxn = 1e5 + 10;

int n, k;

struct Edge{
    int v, nex;
}edge[Maxn<<1];
int head[Maxn], tol;
int sp[Maxn];
bool spi[Maxn];

void init(){
    tol = 0;
    memset(head, -1, sizeof(head));
}

void add(int u, int v){
    edge[tol] = (Edge){v, head[u]}, head[u] = tol++;
}

bool flag, wa[Maxn];
int low[Maxn], dfn[Maxn];
int sta[Maxn], cnt, top, ind;
bool vis[Maxn];
int id[Maxn];

void Tarjan(int u){
    if(flag) return;
    low[u] = dfn[u] = ++ind;
    vis[u] = true;
    sta[++top] = u;
    int v;
    for(int i=head[u]; ~i;i=edge[i].nex){
        v = edge[i].v;
        if(!dfn[v]){
            Tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if(vis[v]) low[u] = min(low[u], dfn[v]);
    }

    if(low[u] == dfn[u]){
        int temp;
        int sum = 0;
        bool f = false;
        cnt++;
        while(1){
            temp = sta[top];
            if(spi[temp]) f = true;
            vis[temp] = false;
            id[temp] = cnt;
            top--;
            sum++;
            if(temp == u) break;
        }
        if(sum > 1 && f){
            flag = true;
            return;
        }
        if(sum > 1) wa[cnt] = true;
    }
}

bool Judge(){
    memset(wa, false, sizeof(wa));
    memset(dfn, 0, sizeof(dfn));
    memset(low, 0, sizeof(low));
    memset(vis, false, sizeof(vis));
    top = cnt = top = 0;
    for(int i=1;i<=n;i++){
        if(flag) return false;
        if(!dfn[i]) Tarjan(i);
    }
    if(flag) return false;
    return true;
}

int ans[Maxn], ans_num;

bool used[Maxn];
void DFS(int u){
    int v;
    if(flag) return;
    if(wa[id[u]]){
        flag = true;
        return;
    }
    used[u] = 1;
    for(int i=head[u];~i;i=edge[i].nex){
        v = edge[i].v;
        if(vis[v] || used[v]) continue;
        DFS(v);
    }
    if(!vis[u]){
        ans[ans_num++] = u;
        vis[u] = true;
    }
}

void solve(){
    flag = false;
    if(!Judge()){
        puts("-1");
//        puts("aaa");
        return;
    }
    int u;
    memset(vis, false, sizeof(vis));
    memset(used, false, sizeof(used));

    for(int i=1;i<=k;i++){
        if(flag){
            puts("-1");
            return;
        }
        u = sp[i];
        if(vis[u] || used[u]) continue;
        DFS(u);
    }
    if(flag){
        puts("-1");
        return;
    }
    printf("%d\n", ans_num);
    for(int i=0;iif(i) printf(" ");
        printf("%d", ans[i]);
    }
}

int main(){
    int m;
    int u, v;
    scanf("%d%d", &n, &k);
    init();

    memset(spi, false, sizeof(spi));
    for(int i=1;i<=k;i++){
        scanf("%d", &sp[i]);
        spi[sp[i]] = true;
    }

    for(int i=1;i<=n;i++){
        scanf("%d", &m);
        u = i;
        while(m--){
            scanf("%d", &v);
            add(u, v);
        }
    }

    solve();
    return 0;
}
/*

4 1
4
1 2
1 3
1 4
1 2

3 3
1 2 3
2 2 3
1 3
0

4 1
4
1 3
1 1
1 2
1 3

*/

你可能感兴趣的:(codeforces,DFS,codeforces,dfs)