tarjan求割点和桥
参考博客:tarjan求割点和桥(割边)
例题:割点
代码(重要的地方在代码中都有注释):
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll M=2e4+10,maxn=3e6+30;
int dfn[M],low[M],tot;
int e[M<<1],k,p[M],k2;
vector<int> g[M];
void tarjan(int x,int f)
{
dfn[x]=low[x]=++tot;
int son=0;
bool flag=false;
for(int i=0;i<g[x].size();i++)
{
int v=g[x][i];
if(!dfn[v])
{
son++;
tarjan(v,x);
if(low[v]>=dfn[x])flag=true;
if(low[v]>dfn[x])//判断桥(割边)
{
e[k++]=x;
e[k++]=v;
}
low[x]=min(low[x],low[v]);
}
else if(v!=f)low[x]=min(low[x],dfn[v]);
//一条无向边实际在g中对应两条有向边,不能通过反向边更新到父节点之上
}
//割点:1.不是根节点满足low[v]>=dfn[x] 2.是根节点且有两个以上的子树
if(flag&&f||f==0&&son>1)p[k2++]=x;
}
int main()
{
freopen("hello.txt","r",stdin);
int n,m;
scanf("%d%d",&n,&m);
int x,y;
while(m--)
{
scanf("%d%d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i,0);
for(int i=0;i<k;)
{
printf("<%d,",e[i++]);
printf("%d> ",e[i++]);
}
printf("\n");
for(int i=0;i<k2;i++)i==k2-1?printf("%d\n",p[i]):printf("%d ",p[i]);
return 0;
}