在看点双
大概看懂了,,,但是实现的时候有一些疑问
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int n,m;
vector<int> pic[500005];
int top=0;
int dfn[500005];
int low[500005];
int order=0;
int stck[500005];
vector<int> dc[500005];
int cnt=0;
void Tarjan(int now,int father)
{
order++;
dfn[now]=order;
low[now]=order;
top++;
stck[top]=now;
bool flag=0;
for(int i=0;i<pic[now].size();i++)
{
int next=pic[now][i];
if(dfn[next]==0)
{
flag=1;
Tarjan(next,now);
low[now]=min(low[now],low[next]);
if(low[next]>=dfn[now])
{
cnt++;
while(stck[top+1]!=next)
{
dc[cnt].push_back(stck[top]);
top--;
}
dc[cnt].push_back(now);
}
}
else if(next!=father)
{
low[now]=min(low[now],dfn[next]);
}
}
if(father==0&&flag==0)
{
dc[++cnt].push_back(now);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
pic[x].push_back(y);
pic[y].push_back(x);
}
for(int i=1;i<=n;i++)
{
if(dfn[i]==0)
{
Tarjan(i,0);
}
}
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++)
{
printf("%d ",dc[i].size());
for(int q=0;q<dc[i].size();q++)
{
printf("%d ",dc[i][q]);
}
printf("\n");
}
return 0;
}
这是满分代码,其中
if(low[next]>=dfn[now])
{
cnt++;
while(stck[top+1]!=next)
{
dc[cnt].push_back(stck[top]);
top--;
}
dc[cnt].push_back(now);
}
改为
if(low[next]>=dfn[now])
{
cnt++;
while(stck[top]!=now)
{
dc[cnt].push_back(stck[top]);
top--;
}
dc[cnt].push_back(now);
}
就错了一部分qaq
有点没弄懂,处理边双的时候不是一定会把整棵子树都处理完才开新子树的处理嘛。。。那样子退栈到now和退完next不是等价的喵 为什么会错呢qaq