luogu P5058 [ZJOI2004]嗅探器 割点

#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef unsigned long long ULL;
const int N = 5e5+10, M = 5e5+10;
int n, m;
int h[N], e[M], ne[M], idx;
int dfn[N], low[N], timestamp;
int stk[N], top;
int dcc_cnt;
//存每个双连通分量里有哪些点
vector<int> dcc[N];
//每个点是不是割点
bool cut[N];
//特判根节点
int root;
int a,b;
void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
void tarjan(int u)
{
    dfn[u] = low[u] = ++ timestamp;
    for (int i = h[u]; ~i; i = ne[i])
    {
        int j = e[i];
        //如果没被遍历过
        if (!dfn[j])
        {
            tarjan(j);
            low[u] = min(low[u], low[j]);
            //                            表示b在j的子树中,就找到了
            if (dfn[u] <= low[j]&&u!=a&&dfn[b]>=dfn[j])
            {
                cut[u] = true;
                return ;
            }
        }
        else
            low[u] = min(low[u], dfn[j]);
    }
}

int main()
{
    idx = n = timestamp = top = dcc_cnt = 0;
    memset(h, -1, sizeof h);
    memset(dfn, 0, sizeof dfn);
    memset(cut, 0, sizeof cut);
    cin>>n;
    while (cin>>a>>b)
    {
        if(a==0&&b==0)
            break;
        add(a, b), add(b, a);
    }
    cin>>a>>b;
    //以a为根
    tarjan(a);
    for(int i=1; i<=n; i++)
        if(cut[i])
        {
            cout<<i<<endl;
            return 0;
        }
    puts("No solution");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/QingyuYYYYY/p/12933260.html