CodeForces - 999E tarjan縮點

CodeForces - 999E

題目

在這裏插入圖片描述

思路

一開始陷入了誤區,我以爲強連通分量縮點之後,每一個點重新連一條邊成一個鏈就是答案,我的答案就是scc-1結果wa了,後來一想因爲兩個強聯通分量直接可能已經有邊了,就不用再加了,看了一篇題解看到說統計入度爲0,後來想想也對,只要讓s連接入度爲0的點,剩下的點都可以經過,那麼縮點,新建一張圖,統計入度爲0的點,即統計入讀爲0的強聯通分量即可。

代碼

#include <iostream>
#include <cstdio>
#include <set>
#include <list>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <sstream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <fstream>
#include <iomanip>
using namespace std;
#define dbg(x) cerr << #x " = " << x <<endl;
typedef pair<int, int> P;
typedef long long ll;

const int MAXN = 5005;
const int MAXM = 5005;
struct Edge
{
    int to, next;
}edge[MAXM];
int Low[MAXN], DFN[MAXN], num[MAXN], Belong[MAXN], Stack[MAXN];
bool Instack[MAXN];
int scc, Index, top;
int head[MAXN], tot;
void addedge(int u, int v)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}
void init()
{
    tot = 0;
    memset(head, -1, sizeof(head));
}
void tarjan(int u)
{
    int v;
    Low[u] = DFN[u] = ++Index;
    Stack[top++] = u;
    Instack[u] = 1;
    for(int i = head[u]; i != -1; i = edge[i].next)
    {
        v = edge[i].to;
        if(!DFN[v])
        {
            tarjan(v);
            Low[u] = min(Low[u], Low[v]);
        }
        else if(Instack[v])
        {
            Low[u] = min(Low[u], DFN[v]);
        }
        
    }
    if(Low[u] == DFN[u])
    {
        scc++;
        do{
            v = Stack[--top];
            Instack[v] = 0;
            Belong[v] = scc;
            num[scc]++;
        }while(u != v);
    }
}

void solve(int N)
{
    memset(DFN, 0, sizeof(DFN));
    memset(Instack, 0, sizeof(Instack));
    memset(num, 0, sizeof(num));
    Index = scc = top = 0;
    for(int i = 1; i <= N; i++)
    {
        if(!DFN[i])
        {
            tarjan(i);
        }
    }
}
P a[MAXN];
int In[MAXN] ={0};
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    init();
    int n, m, s;
    cin >> n >> m >> s;
    for(int i = 0; i < m; i++)
    {
        int u, v;
        cin >> u >> v;
        addedge(u, v);
        a[i].first = u;
        a[i].second = v;
    }
    solve(n);
    /*for(int i = 1; i <= n; i++)
    {
        cout << Belong[i] << ' ';
    }
    cout << endl;*/
    for(int i = 0; i < m; i++)
    {
        int u = a[i].first;
        int v = a[i].second;
        if(Belong[u] != Belong[v])
        {
            In[Belong[v]]++;
        }
    }
    int ans = 0;
    for(int i = 1; i <= scc; i++)
    {
        if(i != Belong[s] && In[i] == 0) ans++;
    }
    cout << ans << endl;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章