zoukankan      html  css  js  c++  java
  • codeforces 962F 点双连通分量

    F. Simple Cycles Edges

    题意:
    n 个点 m 条边的无向图,问哪些边是恰好包含在一个简单环里的。简单环定义:环走一遍,每个点都只出现一次。
    tags:
    考虑 tarjan 缩点,要包含在简单环里,就是点双连通。
    最后在每个点双连通分量里,如边数和点数相同,那就符合。

    // 962F
    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    
    const int N = 100005, M = N*2;
    struct Edge {
        int to,next;
        Edge() {}
        Edge(int to,int next) { this->to=to;  this->next=next; }
    }ed[M];
    int head[N], lnum, esum, index, top, bccnum;
    int dfn[N], low[N], bj[N], Belong[M], num[N];
    bool mark[M], isCut[M];
    stack<int > Stack;
    pair<int, int> E[M];
    vector< int > e2[M];
    void Addedge(int u,int v) { ed[lnum]=Edge(v, head[u]); head[u]=lnum++; }
    void Init_BCC() {
        memset(head, -1, sizeof(head));
        memset(dfn, 0, sizeof(dfn));
        memset(low, 0, sizeof(low));
        memset(mark, false, sizeof(mark));
        memset(Belong, 0, sizeof(Belong));
        memset(isCut, false, sizeof(isCut));
        while(!Stack.empty()) Stack.pop();
        lnum=0;
        index=0;
        bccnum=0;
        esum=0;
    }
    void Tarjan(int u,int fa)
    {   //有自环时不加自环的边
        //点双连通缩点方法:清空路径,枚举E[]数组中存储的路径,建立双向边。
        dfn[u] = low[u] = ++index;
        int child = 0;
        for(int i=head[u]; ~i; i=ed[i].next)
        {
            if(mark[i]) continue;
            int v=ed[i].to;
            mark[i] = mark[i^1] = true;
            Stack.push(i);  //边入栈,需注意此语句要放在判continue之后
            if(!dfn[v])
            {
                ++child;
                Tarjan(v, u);
                low[u]=min(low[u],low[v]);
                if(dfn[u]<=low[v])
                {
                    isCut[u] = true;
                    bccnum++;   //注意这里是N++,建数组时要注意开至少两倍大
                    while(true)
                    {
                        int j=Stack.top();  Stack.pop();
                        //bj[]数组用来标记节点所属的bcc,割点会改变,无意义
                        //E[]存新图的边,esum是其数量,tarjan结束后建双向边
                        if(bj[ed[j].to]!=bccnum){
                            bj[ed[j].to] = bccnum;
                            num[bccnum]++;
                            E[++esum] = make_pair(ed[j].to, bccnum);  // 新图中 ed[j].to -> bccnum+n
                        }
                        if(bj[ed[j^1].to]!=bccnum){
                            bj[ed[j^1].to] = bccnum;
                            num[bccnum]++;
                            E[++esum] = make_pair(ed[j^1].to, bccnum);
                        }
                        Belong[(j>>1)+1]=bccnum;  //标记边所属的bcc
                        e2[bccnum].PB((j>>1)+1);
                        if(i==j) break;
                    }
                }
            }
            else low[u]=min(low[u],dfn[v]); //与有向图区分,此处else不需要判别v节点是否在栈内
        }
        if(fa<0 && child<2) isCut[u]=false; //如果初始节点没有2个以上儿子,标记清0
    }
    
    vector< int > ans;
    int n, m;
    int main()
    {
        Init_BCC();
        scanf("%d%d", &n, &m);
        int u, v;
        rep(i,1,m)
        {
            scanf("%d%d", &u, &v);
            Addedge(u, v);  Addedge(v, u);
        }
        rep(i,1,n) if(!dfn[i]) Tarjan(i, -1);
        rep(i,1,bccnum)
            if(num[i]==e2[i].size()) {
                for(int v : e2[i]) ans.PB(v);
            }
        sort(ans.begin(), ans.end());
        printf("%d
    ", ans.size());
        for(int v : ans) printf("%d ", v);
    
        return 0;
    }
    
  • 相关阅读:
    Leetcode Plus One
    Leetcode Swap Nodes in Pairs
    Leetcode Remove Nth Node From End of List
    leetcode Remove Duplicates from Sorted Array
    leetcode Remove Element
    leetcode Container With Most Water
    leetcode String to Integer (atoi)
    leetcode Palindrome Number
    leetcode Roman to Integer
    leetcode ZigZag Conversion
  • 原文地址:https://www.cnblogs.com/sbfhy/p/8884856.html
Copyright © 2011-2022 走看看