1. 程式人生 > >【UOJ#67】新年的毒瘤(Tarjan)

【UOJ#67】新年的毒瘤(Tarjan)

con space spa href print class ble cpp ==

【UOJ#67】新年的毒瘤(Tarjan)

題面

UOJ

題解

一棵\(n\)個節點的樹顯然有\(n-1\)條邊,在本題中意味著刪去一個點之後還剩下\(n-2\)條邊。那麽找到所有度數為\(m-(n-2)\)的點就好了。但是因為是一棵樹,所以聯通,所以割點不是答案。

#include<iostream>
#include<cstdio>
using namespace std;
#define ll long long
#define MAX 100100
inline int read()
{
    int x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1,dg[MAX];
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;dg[u]++;}
int n,m,dfn[MAX],low[MAX],tim,S[MAX],top,rt,son;
bool cut[MAX];
void Tarjan(int u,int ff)
{
    dfn[u]=low[u]=++tim;
    for(int i=h[u];i;i=e[i].next)
    {
        int v=e[i].v;if(v==ff)continue;
        if(!dfn[v])
        {
            Tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u])
            {
                if(u^rt)cut[u]=true;
                else ++son;
            }
        }
        else low[u]=min(low[u],dfn[v]);
    }
    if(u==rt&&son>1)cut[u]=true;
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=m;++i)
    {
        int u=read(),v=read();
        Add(u,v);Add(v,u);
    }
    for(int i=1;i<=n;++i)if(!dfn[i])Tarjan(rt=i,son=0);
    for(int i=1;i<=n;++i)if(!cut[i]&&(m-dg[i]==n-2))S[++top]=i;
    printf("%d\n",top);
    for(int i=1;i<=top;++i)printf("%d ",S[i]);
    puts("");return 0;
}

【UOJ#67】新年的毒瘤(Tarjan)