zoukankan      html  css  js  c++  java
  • 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 "); continue; } ans = 0; find_cut(); printf("%d ", ans); for (int i = 0; i < en; i += 2) if (edge[i].iscut) printf("%s %s ", name[edge[i].u], name[edge[i].v]); } return 0; }



  • 相关阅读:
    LeetCode 32.使数组唯一的最小增量
    LeetCode 31. 最小的k个数 快速排序+堆排序+二叉搜索树
    LeetCode 30. 最长回文串
    LeetCode 29. 矩形重叠 反向思维
    LeetCode 28. 拼写单词 HashMap赋值给另一个HashMap
    LeetCode 27. 字符串压缩
    Java SSM Spring+Spring MVC+Mybatis整合
    LeetCode 26.岛屿的最大面积 DFS深度遍历问题
    LeetCode 25.最长上升子序列 动态规划
    LeetCode 24.找出数组中出现次数大于二分之一数组长度的数
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6714137.html
Copyright © 2011-2022 走看看