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

来源:互联网 发布:c 图片相似度算法 编辑:程序博客网 时间:2024/05/22 10:56

点击打开链接

描述

在基本的网络搭建完成后,学校为了方便管理还需要对所有的服务器进行编组,网络所的老师找到了小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 71 21 32 33 44 54 65 6
样例输出
21 1 1 4 4 4
#include<stdio.h>#include<stdlib.h>#include<iostream>#include<math.h>#include<vector>#include<string>#include<sstream>#include<algorithm>#include<stack>#include<queue>#include<limits.h>#include<numeric>#include<cstring>#include<map>#include<set>using namespace std;#define eps 1e-8#define LL long longconst LL mod=12357;const int MIN= -1e3;const int MAX= 128 ;const int MAX_N = 1e5 + 10;const int MAX_M = 1e5 + 10;const int MAX_K = 1e4+10;static int N, M, K, T;int head[MAX_N];struct edge{int to;int next;int val;}edge[MAX_M*2];int cnt = 1;static int counter = 0;int vis[MAX_N];int dfn[MAX_N];int low[MAX_N];stack <int> group;int num_group =0 ;set<int> vertex;vector< pair<int, int> > ans_edge;int ans[MAX_N];bool cmp(pair<int, int> a , pair<int, int> b ){if(a.first == b.first) return a.second < b.second;return a.first < b.first;}void addEdge(int u, int v){edge[cnt].to = v;edge[cnt].next = head[u];head[u] = cnt++;}void tarjan(int u, int father){dfn[u] = low[u] = ++counter;int children = 0;group.push(u);for(int i = head[u]; i != 0; i = edge[i].next){int v = edge[i].to;if(v == father) {continue;}if(! dfn[v]){children ++;tarjan(v, u);low[u] = min(low[u], low[v]);if((father == u && children > 1) || (father != u && low[v] >= dfn[u])){//根结点, 并且子树多余1//非根结点,子树的祖先不大于u,即必没有子树指向u的祖先节点vertex.insert(u);}if(low[v] > dfn[u]){ans_edge.push_back(make_pair(min(v, u), max(v,u)));}}else {low[u] = min(low[u], dfn[v]);}}vector<int> tmp;if(low[u] == dfn[u]) {while ( ! group.empty()){int front = group.top();group.pop();if(front == u){tmp.push_back(front);break;}else {tmp.push_back(front);}}}if(tmp.size() != 0){num_group ++;int minst = INT_MAX;for(int i =0; i<tmp.size() ; ++i){minst = min(minst, tmp[i]);}for(int i =0 ; i<tmp.size();++i){ans[tmp[i]] = minst;}}}int main () {cin >> N >> M;for(int i =0; i<M; ++i){int u, v;cin >> u >> v;addEdge(u, v);addEdge(v, u);}tarjan(1,1);/*sort(ans_edge.begin(), ans_edge.end(), cmp);if(vertex.size() == 0) cout <<"Null" << endl;else{auto it = vertex.begin();for(; it != vertex.end(); ++it){printf("%d ", *it);}printf("\n");}for(int i =0; i<ans_edge.size(); ++i){printf("%d %d\n", ans_edge[i].first, ans_edge[i].second);}*/cout << num_group << endl;for(int i =1; i<=N; ++i){printf("%d ", ans[i]);}cout << endl;system("pause");return 0;}


0 0
原创粉丝点击