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<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<list>
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;i<ans_num;i++)
    {
        if(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

*/
發佈了799 篇原創文章 · 獲贊 125 · 訪問量 38萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章