This is an easy problem from uva judge, but has a tedious implementation. http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=1168
Union find disjoint sets.
How I did it
- Read the number of cases .
- Read the total number of people and trees.
- Read and sort the opinion of the people as a graph data structure. Vector vector of set. (opinionGraph)
- Initialize the parent array with the number of people who will listen the fall of trees. (parent is the disjoint set representation).
- Traverse the opinionGraph with 2 fors. If I found 2 equal sets I do union sets.
- I traverse the parent array and check the diferents sub set and insert into an answer set. (This set has the answer the diferents opinions)
- I print the answer set size.
Hints
- Read carefully what does mean opinion of the people.
- We don’t now how many inputs we will have. I am using sstream to parse the input.
- Union find algorithm is really usefull.
- The out is separated by a blank line between 2 consecutive inputs. In the last input we must not print the blank line.
Input analisis
3 4
1 2
3 3
1 3
2 2
3 2
2 4
Code
#include <iostream>
#include <cstdio>
#include <sstream>
#include <vector>
#include <set>
#include <algorithm>
#define ELEMENTS 110
using namespace std;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef set<int> vi;
vector<vi> opinionGraph;
int parent[ELEMENTS];
int rank[ELEMENTS];
void make_sets(int number_of_elements)
{
int i;
for(i = 0; i < number_of_elements; i++)
{
parent[i] = i;
rank[i] = 1;
}
}
int find_set(int element)
{
if(element != parent[element])
parent[element] = find_set(parent[element]);
return parent[element];
}
void set_union(int x, int y)
{
int rx, ry;
rx = find_set(x);
ry = find_set(y);
if(rx == ry)
return;
if(rank[rx] > rank[ry])
{
rank[rx] += rank[ry];
parent[ry] = rx;
}
else
{
rank[ry] += rank[rx];
parent[rx] = ry;
}
}
void read_graph()
{
//opinionGraph.clear();
string str;
stringstream ss;
int people, tree, data;
while(getline(cin,str))
{ int flag = 0;
if(str.size() == 0)
return;
ss<<str;
while(ss>>data)
{
if(!flag)
{
people = data;
flag = 1;
}
else
tree = data;
}
ss.clear();
//cout<<people<<" "<<tree <<people*2<<endl;
opinionGraph[people-1].insert(tree-1);
}
}
int main()
{
int casos,people, trees;
string trash;
scanf("%d", &casos);
getline(cin,trash);//Reading until en of line after casos
getline(cin,trash);//Reading the first empty line
while(casos--)
{
scanf("%d %d",&people, &trees);
opinionGraph.assign(people, vi());
getline(cin,trash);
read_graph();
//Strating union find
make_sets(people);
for(int x=0 ; x<opinionGraph.size(); x++)
for(int y=x+1 ; y<opinionGraph.size(); y++)
if(opinionGraph[x] == opinionGraph[y])
set_union(parent[x], parent[y]);
for(int g=0; g<people; g++)
parent[g] = find_set(g);
int total = 0;
set<int>answer;
for(int h=0; h<people; h++)
answer.insert(parent[h]);
printf("%d\n",answer.size());
if(casos)
printf("\n");
}
return 0;
}