Graph Connectivity UVA, 459(并查集)

Graph Connectivity



UVA,
459

Time Limit: 3000 MS


 Graph Connectivity 

Consider a graph G formed from a large number of nodes connected by edges. G is said to be connected if a path can be found in 0 or more steps between any pair of nodes in G.
For example, the graph below is not connected because there is no path from A to C.

This graph contains, however, a number of subgraphs that are connected, one for each of the following sets of nodes: {A}, {B}, {C}, {D}, {E}, {A,B},
{B,D}, {C,E}, {A,B,D}

A connected subgraph is maximal if there are no nodes and edges in the original graph that could be added to the subgraph and still leave it connected. There are two maximal connected subgraphs
above, one associated with the nodes {ABD} and the other with the nodes {CE}.

Write a program to determine the number of maximal connected subgraphs of a given graph.

Input and Output

The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also
a blank line between two consecutive inputs.

The first line of each input set contains a single uppercase alphabetic character. This character represents the largest node name in the graph. Each successive line contains a pair of uppercase alphabetic
characters denoting an edge in the graph. The sample input section contains a possible input set for the graph pictured above.

Input is terminated by a blank line.

For each test case, the output the number of maximal connected subgraphs. The outputs of two consecutive cases will be separated by a blank line.

Sample Input

1

E
AB
CE
DB
EC

Sample Output

2

题目大意:

求子集的个数。

解题思路:

并查集。

代码:

#include<iostream>
#include<cstdio>
using namespace std;

const int maxn=30;
int t=0,temp,parent[maxn];
bool visited[maxn];

void initial(){
     for(int i=0;i<=maxn;i++)parent[i]=i;
     for(int i=0;i<=maxn;i++)visited[i]=false;
}

int getRoot(int k){
    if(k!=parent[k]) parent[k]=getRoot(parent[k]);
    return parent[k];
}

void Union(int a,int b){parent[a]=b;}

void solve(){
    char ch[3];
    gets(ch);
    temp=ch[0]-'A'+1;
    while(gets(ch)){
        if(!ch[0]) break;//判断是否是空行
        int p=getRoot(ch[0]-'A'+1),q=getRoot(ch[1]-'A'+1);
        if(p!=q) Union(p,q);
    }
}

void output(){
     int cnt=0;
     for(int i=1;i<=temp;i++){
         if(!visited[getRoot(i)]){
             cnt++;
             visited[getRoot(i)]=true;
         }
     }
     printf("%d\n",cnt);
     if(t) printf("\n");
}

int main(){
    while(cin>>t){//原来大的测试也是多组的
        getchar();
        getchar();
        while(t--){
            initial();
            solve();
            output();
        }
    }
    return 0;
}
时间: 2024-10-18 13:42:23

Graph Connectivity UVA, 459(并查集)的相关文章

UVa 11987 并查集 Almost Union-Find

原文戳这 与以往的并查集不同,这次需要一个删除操作.如果是叶子节点还好,直接修改父亲指针就好. 但是如果要是移动根节点,指向它的所有子节点也会跟着变化. 所以要增加一个永远不会被修改的虚拟根节点,这样就可以把一个点从集合中删除而不影响其它的点了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std

UVa 10129 (并查集 + 欧拉路径) Play on Words

题意: 有n个由小写字母的单词,要求判断是否存在某种排列是的相邻的两个单词,前一个单词末字母与后一个单词首字母相同. 分析: 将单词的两个字母看做节点,则一个单词可以看做一条有向边.那么题中所求的排列就等价于该有向图中是否存在欧拉路径. 在判断之前,首先要确定这个图是连通的,代码中用并查集来实现. 回顾一下存在欧拉路径的条件,全都是偶点或者有且仅有两个奇点.我们用deg来记录每个点的度,出度为1,入度为-1. 程序中判断存在欧拉路径的条件就是:deg全为0 或者 有两个不为0的,其中一个为1一个

UVA 11987 并查集删点

并查集删点就是弄个id记录当前点的id,删除的时候将id设为新的id,忽略原来的id,当然还要注意去改变原来集合需要维护的性质比如元素个数等等. #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) m

Bipartite Graph hdu 5313 bitset 并查集 二分图

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5313 题意: 给出n个顶点,m条边,问最多添加多少条边使之构成一个完全二分图 存储结构: bitset     [用法详情:http://blog.csdn.net/piaocoder/article/details/47177891] 用时:624ms 思路: 二分图的总边数即:n*m(假设一个有n个点,另一个有m个点) 题目是给出总共的点数为n,间接求最大的边数 想到一个小学题:给出长度为n的绳子,

CodeForces 466E Information Graph --树形转线性+并查集

题意:有三种操作: 1.新增一条边从y连向x,此前x没有父节点 2.x接到一份文件,(文件标号逐次递增),然后将这份文件一路上溯,让所有上溯的节点都接到这份文件 3.查询某个节点x是否接到过文件F 解法: 首先要知道一个性质,节点u在v的上溯路径上的话要满足: L[u]<=L[v] && R[u] >= R[v] (先进后出) 先将所有的边都读入,dfs得出L[u],R[u],然后将查询分为tot类(tot=总文件种数),记录每一类有那些地方查询了,然后如果type=2,那么记

算法导论——最小生成树:Kruskal算法(利用了并查集)

package org.loda.graph; import org.loda.structure.MinQ; import org.loda.structure.Queue; import org.loda.util.In; /** * * @ClassName: KruskalMST * @Description:Kruskal最小生成树算法 * @author minjun * @date 2015年5月25日 下午10:50:01 * */ public class KruskalMST

Uva 459 Graph Connectivity

题目比较简单,是求子图的个数,用并查集求,我用的树实现,其实还有更简单的,只是我们老师要求而已. 最重要的是要注意输入输出的格式. 1 #include <cstdio> 2 #include<iostream> 3 #define MAX 30 4 using namespace std; 5 6 int CharNum; 7 typedef struct node{ 8 int data_;//节点对应人的编号 9 int rank_;//节点对应的秩 10 int paren

UVA - 10596 - Morning Walk (欧拉回路!并查集判断回路)

UVA - 10596 Morning Walk Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu Submit Status Description Problem H Morning Walk Time Limit 3 Seconds Kamal is a Motashota guy. He has got a new job in Chittagong . So, he has moved to Ch

UVA 572 油田连通块-并查集解决

题意:8个方向如果能够连成一块就算是一个连通块,求一共有几个连通块. 分析:网上的题解一般都是dfs,但是今天发现并查集也可以解决,为了方便我自己理解大神的模板,便尝试解这道题目,没想到过了... 1 #include <cstdio> 2 #include <iostream> 3 #include <sstream> 4 #include <cmath> 5 #include <cstring> 6 #include <cstdlib&