zoj 1311 Network

可以使用并查集也可以使用tarjan算法求割点(更快)
//这是tarjan的

#include <iostream>
#include<algorithm>
#include<sstream>
#include<vector>
#include<cstring>
using namespace std;
const int maxn = 101;
int n, dfn[maxn], anscetor[maxn], ans[maxn], deep;
vector<int> adj[maxn];
void tarjan(int cur, int fa) {
	dfn[cur] = ++deep;
	anscetor[cur] = deep;
	vector<int> to = adj[cur];
	int len = to.size(), nxt, tot;
	tot = 0;
	for (int i = 0; i < len; i++) {
		nxt = to[i];
		if (nxt == fa)continue;
		if (dfn[nxt]) {
			anscetor[cur] = min(anscetor[cur], dfn[nxt]);
		} else {
			tarjan(nxt, cur);
			anscetor[cur] = min(anscetor[cur], anscetor[nxt]);
			tot++;
			if (fa == -1 && tot > 1 || fa != -1 && anscetor[nxt] >= dfn[cur]) {
				ans[cur] = 1;
			}
		}
	}
}
void inti() {
	deep = 0;
	memset(ans, 0, sizeof(ans));
	memset(dfn, 0, sizeof(dfn));
	for (int i = 1; i <= n; i++) {
		adj[i].clear();
	}
}
int main() {
	string s;
	int id, to, i, len, res;
	while (cin >> n && n) {
		inti();
		while (getline(cin, s) && s != "0") {
			istringstream ss(s);
			ss >> id;
			if (id) {
				while (ss >> to) {
					adj[id].push_back(to);
					adj[to].push_back(id);
				}
			}
		}
		tarjan(1, -1);
		res = 0;
		for (i = 1; i <= n; i++) {
			if (ans[i])res++;
		}
		printf("%d\n", res);
	}
}

//这是并查集的

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<unordered_set>
#include<unordered_map>
using namespace std;
const int maxn = 101;
int sz[maxn], fa[maxn], vis[maxn], vis1[maxn];
unordered_map<int, unordered_set<int>> g;
int n;
void inti() {
	for (int i = 1; i <= n; i++) {
		sz[i] = 1;
		fa[i] = i;
	}
}

int fd(int id) {
	return (id == fa[id]) ? id : fa[id] = fd(fa[id]);
}

void unio(int id1, int id2) {
	int f1 = fd(id1);
	int f2 = fd(id2);
	if (f1 == f2)return;
	if (sz[f1] > sz[f2]) {
		fa[f2] = f1;
		sz[f1] += sz[f2];
	} else {
		fa[f1] = f2;
		sz[f2] += sz[f1];
	}
}

int main() {
	int id, i, to, ans, j, t, k, bg;
	char ch[500];
	while (cin >> n && n) {
		cin.ignore();
		inti();
		g.clear();
		while (cin.getline(ch, 400) && ch[0] != '0') {
			if (!ch[0])continue;
			string str = "";
			for (i = 0; ch[i] != ' '; i++) {
				str += ch[i];
			}
			id = stoi(str);
			str = "";
			i++;
			for (; ch[i]; i++) {
				if (ch[i] == ' ') {
					to = stoi(str);
					g[id].insert(to);
					g[to].insert(id);
					str = "";
					continue;
				}
				str += ch[i];
			}
			to = stoi(str);
			g[id].insert(to);
			g[to].insert(id);
		}
		ans = 0;
		for (i = 1; i <= n; i++) {
			inti();
			for (j = 1; j <= n; j++) {
				if (j == i)continue;
				unordered_set<int> st = g[j];
				unordered_set<int>::iterator it = st.begin();
				for (; it != st.end(); it++) {
					if (*it == i)continue;
					unio(j, *it);
				}
			}
			int t = -1;
			int f;
			for (k = 1; k <= n; k++) {
				if (k == i)continue;
				f = fd(fa[k]);
				if (t == -1) {
					t = f;
				} else {
					if (t != f) {
						ans++;
						break;
					}
				}
			}
		}
		printf("%d\n", ans);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值