关于边双的几种求法
  • 板块学术版
  • 楼主hswfwkj_
  • 当前回复2
  • 已保存回复2
  • 发布时间2022/6/8 13:31
  • 上次更新2023/10/27 23:44:37
查看原帖
关于边双的几种求法
374318
hswfwkj_楼主2022/6/8 13:31

这是一般人的求法:

#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;
}

这两种做法都是正确的,但是谁能帮助我理解上面那种求法?

2022/6/8 13:31
加载中...