HDU 3849 By Recognizing These Guys, We Find Social Networks Useful(双连通)

HDU 3849 By Recognizing These Guys, We Find Social Networks Useful

题目链接

题意:说白了就是求一个无向图的桥

思路:字符串hash掉,然后双连通。要注意特判一下假设不是一个连通块。那么答案是0

代码:

#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <map>
using namespace std;

const int N = 10005;
const int M = 200005;
int t, n, m;
map<string, int> hash;
char A[20], B[20];

struct Edge {
	int u, v, id;
	bool iscut;
	Edge() {}
	Edge(int u, int v, int id) {
		this->u = u;
		this->v = v;
		this->id = id;
		this->iscut = false;
	}
} edge[M];

int en, first[N], next[M], hn;
char name[N][20];

void init() {
	en = hn = 0;
	memset(first, -1, sizeof(first));
	hash.clear();
}

int get(char *str) {
	if (!hash.count(str)) {
		strcpy(name[hn], str);
		hash[str] = hn++;
	}
	return hash[str];
}

void add_edge(int u, int v, int id) {
	edge[en] = Edge(u, v, id);
	next[en] = first[u];
	first[u] = en++;
}

int pre[N], dfn[N], dfs_clock, ans = 0;

void dfs_cut(int u, int f) {
	pre[u] = dfn[u] = ++dfs_clock;
	for (int i = first[u]; i + 1; i = next[i]) {
	if (edge[i].id == f) continue;
		int v = edge[i].v;
		if (!pre[v]) {
			dfs_cut(v, edge[i].id);
			dfn[u] = min(dfn[u], dfn[v]);
			if (dfn[v] > pre[u]) {
				ans++;
				edge[i].iscut = edge[i^1].iscut = true;
			}
		} else dfn[u] = min(dfn[u], pre[v]);
	}
}

void find_cut() {
	memset(pre, 0, sizeof(pre));
	for (int i = 0; i < n; i++)
		if (!pre[i]) dfs_cut(i, -1);
}

int parent[N];

int find(int x) {
	return parent[x] == x ?

x : parent[x] = find(parent[x]);
}
int main() {
	scanf("%d", &t);
	while (t--) {
		init();
		scanf("%d%d", &n, &m);
		for (int i = 0; i < n; i++) parent[i] = i;
		int cnt = n;
		for (int i = 0; i < m; i++) {
			scanf("%s%s", A, B);
			int u = get(A), v = get(B);
			add_edge(u, v, i);
			add_edge(v, u, i);
			int pu = find(u), pv = find(v);
			if (pu != pv) {
				cnt--;
				parent[pu] = pv;
			}
		}
		if (cnt > 1) {
			printf("0\n");
			continue;
		}
		ans = 0;
		find_cut();
		printf("%d\n", ans);
		for (int i = 0; i < en; i += 2)
			if (edge[i].iscut)
				printf("%s %s\n", name[edge[i].u], name[edge[i].v]);
	}
	return 0;
}
时间: 2024-10-23 22:42:29

HDU 3849 By Recognizing These Guys, We Find Social Networks Useful(双连通)的相关文章

hdu3849-By Recognizing These Guys, We Find Social Networks Useful:双连通分量

By Recognizing These Guys, We Find Social Networks Useful Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others)Total Submission(s): 2354    Accepted Submission(s): 613 Problem Description Social Network is popular these

hdu3849 By Recognizing These Guys, We Find Social Networks Useful

无向图求桥边数量,按照题目输入顺序输出桥边. 注意存的brig和边的对应关系. #include <iostream> #include <cstdlib> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queu

HDU 3849(桥)

By Recognizing These Guys, We Find Social Networks Useful Problem Description Social Network is popular these days.The Network helps us know about those guys who we are following intensely and makes us keep up our pace with the trend of modern times.

HDU 3849 无向图的割边

By Recognizing These Guys, We Find Social Networks Useful Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others)Total Submission(s): 2319    Accepted Submission(s): 603 Problem Description Social Network is popular these

HDU 3849 无向图求桥

By Recognizing These Guys, We Find Social Networks Useful Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others)Total Submission(s): 2563    Accepted Submission(s): 671 Problem Description Social Network is popular these

HDU 4005 The war(双连通好题)

HDU 4005 The war 题目链接 题意:给一个连通的无向图,每条边有一个炸掉的代价,现在要建一条边(你不不知道的),然后你要求一个你需要的最少代价,保证不管他建在哪,你都能炸掉使得图不连通 思路:炸肯定要炸桥,所以先双连通缩点,得到一棵树,树边是要炸的,那么找一个最小值的边,从该边的两点出发,走的路径中,把两条包含最小值的路径,的两点连边,形成一个环,这个环就保证了最低代价在里面,除了这个环以外的最小边,就是答案,这样的话,就利用一个dfs,搜到每个子树的时候进行一个维护即可 代码:

hdu 4612 Warm up 双连通缩点+树的直径

首先双连通缩点建立新图(顺带求原图的总的桥数,其实由于原图是一个强连通图,所以桥就等于缩点后的边) 此时得到的图类似树结构,对于新图求一次直径,也就是最长链. 我们新建的边就一定是连接这条最长链的首尾,这样就将原图的桥减少了直径个. #include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<algorithm> #include<map&g

HDU 2460 Network(双连通+树链剖分+线段树)

HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链剖分+线段树处理 代码: #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; #pragma comment(linke

Railway HDU - 3394 (点双连通)

Railway HDU - 3394 题意:一个无向图,1求不在任何一个环里的边数:2求在不止一个环里的边数. 第一问明显就是求桥,第二问,如果求出的某个点双连通分量里面边数多于点数,说明不止一个环,那么所有的边都在不止一个环里. 该求点双连通的,,求成了边双连通...要仔细分析问题. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 us