zoukankan      html  css  js  c++  java
  • poj 1144 Network

    Network

    题意:输入n(n < 100)个点,不一定是连通图,问有多少个割点?

    割点:删除某个点之后,图的联通分量增加。

    思路:dfs利用时间戳dfs_clock的特性,点u的low函数low[u]代表以u为根的子树所得连到的最"上面"的祖先的时间戳。

    即当点u存在一个子节点v,而low[v] >= pre[u]时,u就为割点;u-v即为桥,且割点要在最后判断,不能直接在iscut[] = true;处自增。因为cc_cnt代表的是当前的节点,而该节点可能有多个子节点,这样会导致重复计算。

    直接使用了stringstream来读取一行,用了125ms才A.

    #include<iostream>
    #include<sstream>
    #include<cstdio>
    #include<cstring>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<vector>
    #include<cmath>
    #include<stdlib.h>
    #include<time.h>
    using namespace std;
    #define rep0(i,l,r) for(int i = (l);i < (r);i++)
    #define rep1(i,l,r) for(int i = (l);i <= (r);i++)
    #define rep_0(i,r,l) for(int i = (r);i > (l);i--)
    #define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
    #define MS0(a) memset(a,0,sizeof(a))
    #define MS1(a) memset(a,-1,sizeof(a))
    
    const int MAXN = 5100;
    int head[MAXN<<1],tot;
    struct edge{
        int to,w,Next;
    }e[MAXN<<1];
    void ins(int a,int b,int w = 0)
    {
        e[++tot].Next = head[a];
        e[tot].to = b;
        e[tot].w = w;
        head[a] = tot;
    }
    int low[MAXN],pre[MAXN],dfs_clock,cc_cnt;
    bool iscut[MAXN];
    int dfs(int u,int fa)
    {
        int lowu = pre[u] = ++dfs_clock;
        int child = 0;
        for(int id = head[u];id;id = e[id].Next){
            int v = e[id].to;
            if(!pre[v]){
                child++;
                int lowv = dfs(v,u);
                lowu = min(lowu,lowv);//以子节点的low来更新u的low函数;
                if(lowv >= pre[u]) //表示u-v为桥
                    iscut[u] = true;
            }
            else if(v != fa && pre[v] < pre[u])
                lowu = min(lowu,pre[v]);
        }
        if(fa < 0 && child == 1) iscut[u] = 0;
        if(iscut[u]) cc_cnt++;
        low[u] = lowu;
        return lowu;
    }
    int main()
    {
        int n;
        stringstream ss;
        while(scanf("%d",&n) == 1 && n){
            int u,v;
            tot = 0;MS0(head);
            while(scanf("%d",&u) == 1 && u){
                string str;
                getline(cin,str);
                ss.clear();
                ss << str;
                while(ss >> v){
                    ins(u,v);
                    ins(v,u);
                }
            }
            cc_cnt = 0;dfs_clock = 0;//设置好时间戳和初始化
            MS0(iscut);MS0(pre);
            rep1(i,1,n)if(pre[i] == 0)
                dfs(i,-1);
            printf("%d
    ",cc_cnt);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    【Scala】看代码,初步了解Apply方法
    【Scala】通过简洁代码搞明白伴生关系、主构造器和辅助构造器的关系
    【Scala】关于集合的各种知识点
    【Scala】新手入门,基础语法概览
    C#中的异步多线程13 回调
    C#中的异步多线程12 轮询
    C#中的异步多线程11 等待直到结束
    C#中的异步多线程10 BackgroundWorker类
    C#中的异步多线程9 完整的GUI示例
    C#中的异步多线程8 Task.Yield
  • 原文地址:https://www.cnblogs.com/hxer/p/5184066.html
Copyright © 2011-2022 走看看