题目描述:
Ice Skating
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Bajtek is learning to skate on ice. He's a beginner, so his only mode of transportation is pushing off from a snow drift to the north, east, south or west and sliding until he lands in another snow drift. He has noticed that in this way it's impossible to get from some snow drifts to some other by any sequence of moves. He now wants to heap up some additional snow drifts, so that he can get from any snow drift to any other one. He asked you to find the minimal number of snow drifts that need to be created.
We assume that Bajtek can only heap up snow drifts at integer coordinates.
Input
The first line of input contains a single integer n (1 ≤ n ≤ 100) — the number of snow drifts. Each of the following n lines contains two integers *x**i* and *y**i* (1 ≤ xi, yi ≤ 1000) — the coordinates of the i-th snow drift.
Note that the north direction coinсides with the direction of Oy axis, so the east direction coinсides with the direction of the Ox axis. All snow drift's locations are distinct.
Output
Output the minimal number of snow drifts that need to be created in order for Bajtek to be able to reach any snow drift from any other one.
Examples
Input
Copy
2
2 1
1 2
Output
Copy
1
Input
Copy
2
2 1
4 1
Output
Copy
0
思路:
题目是说给一些点,这些点只有在x坐标相同或者y坐标相同才能相互连接,现在为了让这些点能够全部连通问需要再加几个点。这题一开始可能会觉得有点麻烦,因为这是好多个点,我怎么知道那些点能够相互连通那些点不能,加点又要加在什么地方。但其实不用考虑加点在什么地方,我们只需要关注哪些点是连通的就行了。把这些点建成一个图,可以连通的建一条边,然后就是图上的强连通分量的数目了。一个强连通分量内点是可以相互到达的,有n个强连通分量我们就把强连通分量再连起来这些点就组成了一个强连通分量。怎么连,只要再建n-1条边就行了。这n-1条边实际上就对应的是加建的点。然而我忘了tarjan怎么写,照抄书上的另一种算法,但好像那个模板有点问题,于是看了tarjan再写就对了。
代码:
#include <iostream>
#include <stack>
#include <vector>
#define max_n 1005
using namespace std;
typedef pair<int,int> PII;
vector<PII> vec;
int head[max_n];
int cnt = 0;
struct edge
{
int v;
int nxt;
}e[max_n<<1];
void add(int u,int v)
{
++cnt;
e[cnt].v = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
int n,m;
int idx = 0;
int Bcnt;
int instack[max_n];
int dfn[max_n];
int low[max_n];
int belong[max_n];
stack<int> s;
void tarjan(int u)
{
dfn[u] = low[u] = ++idx;
s.push(u);
instack[u]=1;
int v;
for(int i = head[u];i;i=e[i].nxt)
{
v = e[i].v;
if(!dfn[v])
{
tarjan(v);
low[u] = min(low[u],low[v]);
}
else if(instack[v])
{
low[u] = min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u])
{
Bcnt++;
do
{
v=s.top();
s.pop();
instack[v]=0;
belong[v]=Bcnt;
}while(u!=v);
}
}
int main()
{
cin >> n;
for(int i = 0;i<n;i++)
{
int x,y;
cin >> x >> y;
vec.push_back(PII(x,y));
}
for(int i = 0;i<n;i++)
{
for(int j = i+1;j<n;j++)
{
if(vec[i].first==vec[j].first||vec[i].second==vec[j].second)
{
add(i,j);
add(j,i);
}
}
}
for(int i = 0;i<n;i++)
{
if(!dfn[i])
{
tarjan(i);
}
}
cout << Bcnt-1 << endl;
return 0;
}