这是一般人的求法:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#define getchar() (S == T && (T = (S = BB) + fread(BB, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
char BB[1 << 15], *S = BB, *T = BB;
using namespace std;
const int MAXN=1e5+10;
inline int read()
{
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
struct node
{
int u,v,w,nxt;
}edge[MAXN];
int head[MAXN],num=1;
inline void AddEdge(int x,int y)
{
edge[num].u=x;
edge[num].v=y;
edge[num].nxt=head[x];
head[x]=num++;
}
int dfn[MAXN],low[MAXN],vis[MAXN],tot=0,colornum=0,color[MAXN],inder[MAXN];
int fuck[5001][5001];
stack<int>s;
void tarjan(int now,int fa)
{
dfn[now]=low[now]=++tot;
s.push(now);
vis[now]=1;
for(int i=head[now];i!=-1;i=edge[i].nxt)
{
if(!dfn[edge[i].v]&&edge[i].v!=fa)
tarjan(edge[i].v,now),low[now]=min(low[now],low[edge[i].v]);
if(vis[edge[i].v]&&edge[i].v!=fa) low[now]=min(low[now],dfn[edge[i].v]);
}
if(dfn[now]==low[now])
{
int h=0;
colornum++;
do
{
h=s.top();
color[h]=colornum;
s.pop();
}while(h!=now);
}
}
int main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
#else
#endif
memset(head,-1,sizeof(head));
int N=read(),M=read();
for(int i=1;i<=M;i++)
{
int x=read(),y=read();
AddEdge(x,y);
AddEdge(y,x);
}
tarjan(1,0);
for(int i=1;i<=num-1;i++)
if(color[edge[i].u]!=color[edge[i].v]&&fuck[edge[i].u][edge[i].v]==0)
fuck[edge[i].u][edge[i].v]=1,
inder[color[edge[i].u]]++,
inder[color[edge[i].v]]++;
int ans=0;
for(int i=1;i<=colornum;i++)
if(inder[i]==2)//双向边
ans++;
printf("%d",(ans+1)>>1);
return 0;
}
这是我自己的求法:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m,q,tot,top,res,cnt;
int ver[N],nxt[N],head[N];
int dep[N],ins[N],dfn[N],stk[N],low[N];
vector<int>g[N];
inline void add(int x,int y)
{
ver[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
void tarjan(int x,int fa)
{
stk[++top]=x;
dfn[x]=low[x]=++res;
for(int i=head[x];i;i=nxt[i])
{
int y=ver[i];
if(!dfn[y])
{
tarjan(y,x);
low[x]=min(low[x],low[y]);
if(dfn[x]<low[y])
{
cnt++;
while(stk[top+1]!=y)
{
g[cnt].push_back(stk[top]);
ins[stk[top--]]=cnt;
}
}
}
else if(y!=fa)low[x]=min(low[x],dfn[y]);
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
add(x,y);
add(y,x);
}
add(0,1);
tarjan(0,0);
for(int i=1;i<=cnt;i++)
{
cout<<"Case "<<i<<':'
for(int j=0;j<g[i].size();j++)
cout<<g[i][j]<<' ';
cout<<'\n';
}
return 0;
}
这两种做法都是正确的,但是谁能帮助我理解上面那种求法?