您的位置:首页 > 其它

hihocoder #1190 : 连通性·四 点双联通分量

2017-04-02 22:08 302 查看
http://hihocoder.com/problemset/problem/1190?sid=1051696

先抄袭一下

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

小Hi和小Ho从约翰家回到学校时,网络所的老师又找到了小Hi和小Ho。

老师告诉小Hi和小Ho:之前的分组出了点问题,当服务器(上次是连接)发生宕机的时候,在同一组的服务器有可能连接不上,所以他们希望重新进行一次分组。这一次老师希望对连接进行分组,并把一个组内的所有连接关联的服务器也视为这个组内的服务器(注意一个服务器可能属于多个组)。

这一次的条件是对于同一个组满足:当组内任意一个服务器宕机之后,不会影响组内其他服务器的连通性。在满足以上条件下,每个组内的边数量越多越好。

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

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 100000 + 20;
struct Edge {
int u, v, id;
int tonext;
}e[maxn * 2];
int first[maxn], num;
void addEdge(int u, int v, int id) {
++num;
e[num].u = u, e[num].v = v, e[num].id = id;
e[num].tonext = first[u];
first[u] = num;
}
int DFN[maxn], low[maxn], when;
int st[maxn], top;
int id[maxn], toSelid;
int ans[maxn];
bool flag[maxn];
const int root = 1;
void tarjan(int cur, int fa) {
DFN[cur] = low[cur] = ++when;
for (int i = first[cur]; i; i = e[i].tonext) {
int v = e[i].v;
if (v == fa) continue;
if (!DFN[v]) {
st[++top] = e[i].id;
tarjan(v, cur);
low[cur] = min(low[cur], low[v]);
if (low[v] >= DFN[cur]) { //这个是割点,特殊情况是两点一边,同一个割点会多次判定
++toSelid;
do {
int eID = st[top--];
id[eID] = toSelid; // 这条边属于那一个块
ans[toSelid] = min(ans[toSelid], eID);
} while (st[top + 1] != e[i].id);
}

} else if (DFN[cur] > DFN[v]) { //5-->4反向边,但是4同样会枚举4-->5这条边,这是没用的边,已经统计了
low[cur] = min(low[cur], DFN[v]);
st[++top] = e[i].id; //反向边
}
}
}
void solveTarjan(int n) {
memset(DFN, 0, sizeof DFN);
memset(low, 0, sizeof low);
when = top = toSelid = 0;
for (int i = 1; i <= n; ++i) {
if (!DFN[i]) tarjan(i, i);
}
}
void work() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= m; ++i) {
int u, v;
cin >> u >> v;
addEdge(u, v, i);
addEdge(v, u, i);
}
memset(ans, 0x3f, sizeof ans);
solveTarjan(n);
cout << toSelid << endl;
for (int i = 1; i <= m; ++i) {
cout << ans[id[i]] << " ";
}
}

int main() {
#ifdef local
freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
work();
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: