这道题用两种最常用的方法做,一种是用并查集,一种使用图的深度优先遍历
/*
HDOJ 1232 畅通工程
用并查集做
*/
#include <iostream>
using namespace std;
#define INF 999
int N,M;
int p[1005];
int rank[1005];
int Find(int x)
{
int y,w,root;
y=x;
while(p[y] != y)
{
y=p[y];
}
root=y;
y=x;
while(p[y] != y)
{
w=p[y];
p[y]=root;
y=w;
}
return root;
}
void Union(int x,int y)
{
if(rank[x] <= rank[y])
{
p[x]=y;
if(rank[x] == rank[y])
rank[y]++;
}
else
p[y]=x;
}
void Make_set(int n)
{
for(int i=0;i<=n;i++)
{
p[i]=i;
rank[i]=0;
}
}
int main()
{
int i,j,a,b,x,y,f;
while(scanf("%d",&N) && N)
{
Make_set(N);
cin>>M;
if(M == 0)
{
printf("%d\n",N-1);
continue;
}
for(i=1;i<=M;i++)
{
cin>>a>>b;
x=Find(a);
y=Find(b);
if(x != y)
Union(x,y);
}
f=0;
for(i=1;i<=N;i++)
if(p[i]==i)
f++;
printf("%d\n",f-1);
}
return 0;
}
/*
HDOJ 1232 畅通工程
用图的DFS做,看看有多少个连通分支
*/
#include <iostream>
using namespace std;
int graph[1005][1005];
bool visited[1005];
int N,M,f;
void Create_Graph()
{
int i,j,a,b;
for(i=1;i<=N;i++)
for(j=1;j<=N;j++)
{
graph[i][j]=0;
}
for(i=0;i<M;i++)
{
cin>>a>>b;
graph[a][b]=1;
graph[b][a]=1;
}
}
void DFS(int v)
{
visited[v]=1;
for(int i=1;i<=N;i++)
if(graph[v][i] && !visited[i])
DFS(i);
}
void DFS_Traverse()
{
for(int i=1;i<=N;i++)
visited[i]=0;
f=0;
for(i=1;i<=N;i++)
{
if(!visited[i])
{
f++;
DFS(i);
}
}
}
int main()
{
while(cin>>N)
{
if(N == 0)
break;
cin>>M;
if(M == 0)
cout<<N-1<<endl;
else
{
Create_Graph();
DFS_Traverse();
cout<<f-1<<endl;
}
}
return 0;
}