hihoCoder_#1184_连通性二·边的双连通分量

#1184 : 连通性二·边的双连通分量

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

在基本的网络搭建完成后,学校为了方便管理还需要对所有的服务器进行编组,网络所的老师找到了小Hi和小Ho,希望他俩帮忙。

老师告诉小Hi和小Ho:根据现在网络的情况,我们要将服务器进行分组,对于同一个组的服务器,应当满足:当组内任意一个连接断开之后,不会影响组内服务器的连通性。在满足以上条件下,每个组内的服务器数量越多越好。

比如下面这个例子,一共有6个服务器和7条连接:

其中包含2个组,分别为{1,2,3},{4,5,6}。对{1,2,3}而言,当1-2断开后,仍然有1-3-2可以连接1和2;当2-3断开后,仍然有2-1-3可以连接2和3;当1-3断开后,仍然有1-2-3可以连接1和3。{4,5,6}这组也是一样。

老师把整个网络的情况告诉了小Hi和小Ho,小Hi和小Ho要计算出每一台服务器的分组信息。

输入

第1行:2个正整数,N,M。表示点的数量N,边的数量M。1≤N≤20,000, 1≤M≤100,000

第2..M+1行:2个正整数,u,v。表示存在一条边(u,v),连接了u,v两台服务器。1≤u<v≤N

保证输入所有点之间至少有一条连通路径。

输出

第1行:1个整数,表示该网络的服务器组数。

第2行:N个整数,第i个数表示第i个服务器所属组内,编号最小的服务器的编号。比如分为{1,2,3},{4,5,6},则输出{1,1,1,4,4,4};若分为{1,4,5},{2,3,6}则输出{1,2,2,1,1,2}

样例输入

6 7
1 2
1 3
2 3
3 4
4 5
4 6
5 6

样例输出

2
1 1 1 4 4 4

分析:做法其实和有向图的强连通分量差不多。有一点需要注意,无向图不需要判断点是否在栈中。为什么无向图不用标记呢,那时因为,边是无向的,有边从u->v同时也必有边v->u 由于u之前被标记过,而遍历到当前结点v 又不是通过w(u,v)这条边过来的,则必还存在另一条路径可以使u 和v 是相通的,从而u,v是双连通的。

有关图的强连通分量,割点,桥,块,参照:http://blog.csdn.net/shiqi_614/article/details/7833628

题目链接:http://hihocoder.com/problemset/problem/1184

代码清单:

#include<map>
#include<set>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;

const int maxn = 20000 + 5;
const int maxv = 100000 + 5;

int N,M,a,b;
vector<int>graph[maxn];
int dfn[maxn];
int low[maxn];
stack<int>sta;
bool InStack[maxn];
int belong[maxn];
int min_num[maxn];
int idx,sccno;

void init(){
    for(int i=0;i<maxn;i++)
        graph[i].clear();
    while(!sta.empty()) sta.pop();
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(belong,0,sizeof(belong));
    memset(min_num,0,sizeof(min_num));
    memset(InStack,false,sizeof(InStack));
    idx=0; sccno=0;

}

void input(){
    scanf("%d%d",&N,&M);
    for(int i=0;i<M;i++){
        scanf("%d%d",&a,&b);
        graph[a].push_back(b);
        graph[b].push_back(a);
    }
}

void tarjan(int u,int father){
    low[u]=dfn[u]=++idx;
    InStack[u]=true;
    sta.push(u);
    bool flag=true;
    for(int i=0;i<graph[u].size();i++){
        int v=graph[u][i];
        if(v==father) continue;//
        if(!dfn[v]){
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
        }
        else //无向图不需要用栈来标记
            low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u]){
        sccno++;
        min_num[sccno]=u;
        while(!sta.empty()){
            int j=sta.top();
            sta.pop();
            InStack[j]=false;
            belong[j]=sccno;
            min_num[sccno]=min(min_num[sccno],j);
            if(j==u) break;
        }
    }
}

void solve(){
//    for(int i=1;i<=N;i++){
//        if(!dfn[i]) tarjan(i,i);
//    }
    tarjan(1,1);
    printf("%d\n",sccno);
    for(int i=1;i<=N;i++){
        printf("%d ",min_num[belong[i]]);
    }
    printf("\n");
}

int main(){
    init();
    input();
    solve();
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-27 12:08:04

hihoCoder_#1184_连通性二·边的双连通分量的相关文章

hihoCoder #1184 : 连通性二&#183;边的双连通分量(边的双连通分量模板)

#1184 : 连通性二·边的双连通分量 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在基本的网络搭建完成后,学校为了方便管理还需要对所有的服务器进行编组,网络所的老师找到了小Hi和小Ho,希望他俩帮忙. 老师告诉小Hi和小Ho:根据现在网络的情况,我们要将服务器进行分组,对于同一个组的服务器,应当满足:当组内任意一个连接断开之后,不会影响组内服务器的连通性.在满足以上条件下,每个组内的服务器数量越多越好. 比如下面这个例子,一共有6个服务器和7条连接: 其中包

hihoCoder_#1190_连通性&#183;四&#183;点的双连通分量(块)

#1190 : 连通性·四 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho从约翰家回到学校时,网络所的老师又找到了小Hi和小Ho. 老师告诉小Hi和小Ho:之前的分组出了点问题,当服务器(上次是连接)发生宕机的时候,在同一组的服务器有可能连接不上,所以他们希望重新进行一次分组.这一次老师希望对连接进行分组,并把一个组内的所有连接关联的服务器也视为这个组内的服务器(注意一个服务器可能属于多个组). 这一次的条件是对于同一个组满足:当组内任意一个服务器宕

#1184 : 连通性二&#183;边的双连通分量

贴板子.求割边.将>改为>=即可判断u是否为割点. #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f; const int maxn=20008; const int maxm=100008; struct fuck{ int u,v,next; bool ban; }edge[maxm<<1];

[HIHO1184]连通性二&#183;边的双连通分量(双连通分量)

题目链接:http://hihocoder.com/problemset/problem/1184 题意裸,写个博客记下输出姿势. 1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7 ┓┏┓┏┓┃ 8 ┛┗┛┗┛┃ 9 ┓┏┓┏┓┃ 10 ┛┗┛┗┛┃ 11 ┓┏┓┏┓┃ 12 ┛┗┛┗┛┃ 13 ┓┏┓┏┓┃ 14 ┃┃┃┃┃┃ 15 ┻┻┻┻┻┻ 16 */ 17 #include <

双连通分量(点-双连通分量&amp;边-双连通分量)

概念: 双连通分量有点双连通分量和边双连通分量两种.若一个无向图中的去掉任意一个节点(一条边)都不会改变此图的连通性,即不存在割点(桥),则称作点(边)双连通图. 一个无向图中的每一个极大点(边)双连通子图称作此无向图的点(边)双连通分量.求双连通分量可用Tarjan算法.--百度百科 Tip:先学一下tarjan算法以及求割点割边的算法之后,再看会比较好理解一些. 点双连通和边双连通 连通的概念:在无向图中,所有点能互相到达 连通分量:互相联通的子图 点双连通:删掉一个点之后,图仍联通 边双连

双连通分量和强连通分量的总结

[双连通分量] 一.边双连通分量定义 在分量内的任意两个点总可以找到两条边不相同的路径互相到达.总而言之就是一个圈,正着走反着走都可以相互到达,至少只有一个点. 二.点双连通分量的定义 参照上面,唯一的不同:任意两个点可以找到一个点不同的路径互相到达.也是一个圈,正反走都可以,至少为一个点. 三.边.点双连通分量模板代码要注意的地方 边双连通分量: 1.每个节点的所有儿子遍历后才开始计算分量大小,请与点双连通相区分: 2.割顶只能属于一个分量,请与割边区分:(容易搞混) 3.要注意j是否是i的父

hihoCoder #1190 : 连通性&#183;四(点的双连通分量模板)

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho从约翰家回到学校时,网络所的老师又找到了小Hi和小Ho. 老师告诉小Hi和小Ho:之前的分组出了点问题,当服务器(上次是连接)发生宕机的时候,在同一组的服务器有可能连接不上,所以他们希望重新进行一次分组.这一次老师希望对连接进行分组,并把一个组内的所有连接关联的服务器也视为这个组内的服务器(注意一个服务器可能属于多个组). 这一次的条件是对于同一个组满足:当组内任意一个服务器宕机之后,不会影响组内其他服务

Hiho1186/ 第五十五周 连通性&#183;四 点双连通分量

题意: 给出一幅n个点m条边的连通图 求图中有几个点双连通分量 并输出每条边所在点双连通分量中所有边的编号最小边的编号 代码: #include<iostream> #include<cstdio> #include<cstring> #define maxn 20050 #define maxm 200050 using namespace std; struct node{ int id,to,next; }edge[maxm]; int head[maxn]; i

连通分量模板:tarjan: 求割点 &amp;&amp; 桥 &amp;&amp; 缩点 &amp;&amp; 强连通分量 &amp;&amp; 双连通分量 &amp;&amp; LCA(最近公共祖先)

PS:摘自一不知名的来自大神. 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合. 3.点连通度:最小割点集合中的顶点数. 4.割边(桥):删掉它之后,图必然会分裂为两个或两个以上的子图. 5.割边集合:如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合. 6.边连通度:一个图的边连通度的定义为,最