1 条题解

  • 0
    @ 2025-10-8 16:57:11
    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+10;
    vector<pair<int,int>>G1[N];
    vector<int>G2[N];
     
    int tsp,cnt,dfn[N],low[N],scc[N];
    stack<int>stk;bool instk[N];
    
    void tarjan(int x, int in_id) 
    {
        dfn[x]=low[x]=++tsp;
        stk.push(x);instk[x]=1;
        for(auto i:G1[x]) if(i.second!=in_id)
    	{
            int y=i.first,id=i.second;
            if(dfn[y]==0) 
    		{
                tarjan(y,id);
                low[x]=min(low[x],low[y]);
            }
            else if(instk[y])low[x]=min(low[x],dfn[y]);
        }
        if(dfn[x]==low[x])
        {
    	    cnt++;
    	    for(int z=-1;z!=x;)
    	    {
    	    	z=stk.top();stk.pop();instk[z]=0;
    	    	scc[z]=cnt;
    	    }
    	}
    }
    
    int ans,fa[N]/*并查集中的父节点*/, dep[N]/*缩点之后的树上的深度*/, up[N]/*缩点之后的树上的父节点*/;
    void dfs_scc(int x) 
    {
        for(int y:G2[x])if(dep[y]==0)
        {
            dep[y]=dep[x]+1;
            up[y] =x;
            dfs_scc(y);
        }
    }
     
    int findfa(int x){ return (x==fa[x]) ? x : (fa[x] = findfa(fa[x]));}
    void solve(int x,int y)
    {
        x=findfa(x),y=findfa(y);
        while(x!=y)
        {
            if(dep[x]<dep[y])swap(x,y);
            ans--;// x到up[x]的边从桥边变为非桥边
            fa[x]=findfa(up[x]);//不能是:fa[x] = up[x];
            x=findfa(x);//此处也可以:x = fa[x];
        }
    }
     
    int main()
    {
        int T=0,n,m;
        while(scanf("%d%d",&n,&m)!=EOF && !(n==0 && m==0) ) 
        {
            memset(G1,0,sizeof(G1));
            for(int i=1,x,y;i<=m;i++)
            {
                scanf("%d%d", &x,&y);
                G1[x].push_back({y,i});
                G1[y].push_back({x,i});
            }
             
            tsp=cnt=0;memset(low,0,sizeof low);memset(dfn,0,sizeof dfn);
    		memset(scc,0,sizeof(scc));memset(instk,0,sizeof(instk));
            tarjan(1, 0);
             
            memset(G2,0,sizeof(G2));
            map<pair<int,int>,bool>mp;
            for(int i=1;i<=n;i++)for(auto j:G1[i])
            {
                int x=scc[i], y=scc[j.first];if(x>y)swap(x,y);
                if(x!=y && !mp[{x,y}])
                {
                    G2[x].push_back(y);
                    G2[y].push_back(x);
                    mp[{x,y}]=1;
                }
            }
             
            memset(up,0,sizeof(up));memset(dep, 0, sizeof(dep));
            dep[1]=1,dfs_scc(1);
             
            for(int i=1;i<=cnt;i++) fa[i]=i;
            printf("Case %d:\n",++T);
            int q;scanf("%d",&q);
            ans=cnt-1;
            while(q--)
            {
                int x,y;scanf("%d%d",&x,&y);
                x=scc[x],y=scc[y];
                if(x!=y) solve(x,y);
                printf("%d\n", ans);
            }
            printf("\n");
        }
        return 0;
    }
    
    • 1

    *【缩点】加边+统计割边[POJ3694]网络(好题)

    信息

    ID
    1452
    时间
    1000ms
    内存
    512MiB
    难度
    8
    标签
    递交数
    262
    已通过
    34
    上传者