• hdu3394--Railway(点的双连通分量)


    一个公园中有 n 个景点,景点之间通过无向的道路来连接(明显的点双

    ),如果至少两个环公用一条路,路上的游客就会发生冲突;如果一条路不属于任何的环,这条路就没必要修

    问,有多少路不必修,有多少路会发生冲突

    每一个连通块中,如果边数大于点数,这个块中所有的边全部是冲突边。

    所有桥为不需要修建的路。

    点双连通分量:对于一个连通图,如果任意两点至少存在两条“点不重复”的路径,则说这个图是点双连通的(一般简称双连通),简单来说就是任意两条边都在同一个简单环中,即内部无割顶。
    多余边:不在任何环中,一定是桥。

    冲突边:如果一个环内的边数大于点数,那么这个环内所有边都是“冲突边”。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <stack>
    using namespace std;
    typedef long long ll;
    #define cls(s,h) memset(s,h,sizeof s)
    const int maxn = 1e5 + 7;
    int n , m ;
    int tot;
    struct  edge
    {
        int to,from,nxt;
    }e[maxn << 1];
    
    int head[maxn];
    void add_edge(int u , int v ){
        e[tot].from = u ;
        e[tot].to = v;
        e[tot].nxt = head[u];
        head[u] = tot++;
    }
    
    int dfn[maxn],low[maxn],idx;
    stack<edge> stk;
    set<int> bcc;
    int cut; //brige
    int ans; //the outway brige
    int flag;
    void tanjan(int u , int pre){
        dfn[u] = low[u] = ++idx;
        for(int i = head[u]; ~i;i = e[i].nxt){
            int v = e[i].to;
            if(v == pre) continue;
            if(!dfn[v]){
                stk.push(e[i]);
                tanjan(v,u);
                low[u] = min(low[u],low[v]);
                if(low[v] >= dfn[u]){//割点
                    edge tmp;
                    int cnt = 0;
                    bcc.clear();
                    //bcc[++flag].push(e[i]);
                    do{//找v.DCC的子集
                        cnt++;//子集的边数
                        tmp = stk.top();
                        stk.pop();
                        //点数
                        bcc.insert(tmp.from);
                        bcc.insert(tmp.to);
                    }while(tmp.from != u || tmp.to != v);
                    if(cnt > bcc.size()) ans += cnt;
                   // flag ++;
                }
                if(low[v] > dfn[u]) ++cut;
            }else if(dfn[v] < dfn[u]){
                stk.push(e[i]);
                low[u] = min(low[u],dfn[v]);
            }
        }
    }
    
    void init(){
        cls(head,-1);
        cls(dfn,0);
        flag = ans = cut = tot = idx = 0;
    }
    
    int main(int argc, char const *argv[])
    {
        while(scanf("%d %d",&n,&m) && n + m){
            int u , v;
            init();
            for(int i = 1;i <= m ;i ++){
                scanf("%d %d",&u,&v);
                add_edge(u,v);
                add_edge(v,u);
            }
            for(int i = 1;i <= n;i ++){
                if(!dfn[i]) tanjan(i,-1);
            }
            printf("%d %d
    ",cut,ans );
        }
        return 0;
    }
    View Code
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <stack>
    using namespace std;
    typedef long long ll;
    #define cls(s,h) memset(s,h,sizeof s)
    const int maxn = 1e5 + 7;
    int n , m ;
    int tot;
    struct  edge
    {
        int to,from,nxt;
    }e[maxn << 1];
    
    int head[maxn];
    void add_edge(int u , int v ){
        e[tot].from = u ;
        e[tot].to = v;
        e[tot].nxt = head[u];
        head[u] = tot++;
    }
    
    int dfn[maxn],low[maxn],idx;
    stack<edge> stk;
    set<int> bcc;
    int cut; //brige 桥
    int ans; //the outway brige 冲突的边
    int flag;
    void tanjan(int u , int pre){
        dfn[u] = low[u] = ++idx;
        for(int i = head[u]; ~i;i = e[i].nxt){
            int v = e[i].to;
            if(v == pre) continue;
            if(!dfn[v]){
                stk.push(e[i]);
                tanjan(v,u);
                low[u] = min(low[u],low[v]);
                if(low[v] >= dfn[u]){//割点 割点判定法则
                    edge tmp;
                    int cnt = 0;
                    bcc.clear();
                    //bcc[++flag].push(e[i]);
                    do{//找v.DCC的子集
                        cnt++;//子集的边数
                        tmp = stk.top();
                        stk.pop();
                        //点数
                        bcc.insert(tmp.from);
                        bcc.insert(tmp.to);
                    }while(tmp.from != u || tmp.to != v);
                    if(cnt > bcc.size()) ans += cnt;
                   // flag ++;
                }
                if(low[v] > dfn[u]) ++cut;
            }else if(dfn[v] < dfn[u]){
                stk.push(e[i]);
                low[u] = min(low[u],dfn[v]);
            }
        }
    }
    
    void init(){
        cls(head,-1);
        cls(dfn,0);
        flag = ans = cut = tot = idx = 0;
    }
    
    int main(int argc, char const *argv[])
    {
        while(scanf("%d %d",&n,&m) && n + m){
            int u , v;
            init();
            for(int i = 1;i <= m ;i ++){
                scanf("%d %d",&u,&v);
                add_edge(u,v);
                add_edge(v,u);
            }
            for(int i = 1;i <= n;i ++){
                if(!dfn[i]) tanjan(i,-1);
            }
            printf("%d %d
    ",cut,ans );
        }
        return 0;
    }
    更新
  • 相关阅读:
    cocos2d-x之物理引擎初试
    cocos2d-x之猜数字游戏
    cocos2d-x之加法计算器
    cocos2d-x之悦动的小球
    cocos2d-x之多个移动的小球
    cocos2d-x之json文件读取初试
    cocos2d-x之xml文件读取初试
    cocos2d-x之使用plist文件初试
    cocos2d-x之文件读写
    cocos2d-x之首选项数据初试
  • 原文地址:https://www.cnblogs.com/DWVictor/p/11333607.html
Copyright © 2020-2023  润新知