【UOJ67】【JZOJ4679】种树

来源:互联网 发布:away3d教程 源码 编辑:程序博客网 时间:2024/06/07 04:59

Description

这里写图片描述
原题在:http://uoj.ac/problem/67

Solution

首先确定树的概念:有n个点,n-1条边的无向连通图。

那么现在我们有n个点m条边,我们现在要删除一个点u首先要满足原图要联通,然后才满足树的条件。

那么,用Tarjan求出所有割点,那么非割点去掉后仍保持联通,那么在此基础上判断是否是树即可。

Code

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)#define N 100001#define M 200001#define ll long longusing namespace std;int to[M],next[M],last[M],num=0;int ds[N];int c[N];bool bz[N];bool r[N];void link(int x,int y){    num++;    to[num]=y;    next[num]=last[x];    last[x]=num;}int dfn[N],low[N];int dep=0;int cut[N];void tarjan(int x){    low[x]=dfn[x]=++dep;    for(int i=last[x];i;i=next[i])    {        int v=to[i];        if(!dfn[v])        {            tarjan(v);            low[x]=min(low[x],low[v]);            if(low[v]>=dfn[x]) cut[x]++;        }        else low[x]=min(low[x],dfn[v]);    }}int main(){    int n,m;    cin>>n>>m;    fo(i,1,m)    {        int u,v;        scanf("%d %d",&u,&v);        ds[u]++;        ds[v]++;        link(u,v);        link(v,u);    }    fo(i,1,n) if(!dfn[i]) cut[i]--,tarjan(i);    fo(i,1,n)    if(cut[i]<=0)    {        if(n-2==m-ds[i]) c[++c[0]]=i;    }    cout<<c[0]<<endl;    fo(i,1,c[0]) printf("%d ",c[i]);}
1 0
原创粉丝点击