这两个题目的重点有两处
1:
if(x!=y)
这个判断标志着两个点是否联通,如果不连通,就让它连起来。
2:
int find(int n)//查找爸爸
{
return f[n]==n?f[n]:find(f[n]);
}
题目和代码
畅通工程
时间限制:
2000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?
-
输入
-
测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
注意:两个城市之间可以有多条道路相通,也就是说
3 3
1 2
1 2
2 1
这种输入也是合法的
当N为0时,输入结束,该用例不被处理。
输出
- 对每个测试用例,在1行里输出最少还需要建设的道路数目。 样例输入
-
4 2 1 3 4 3 3 3 1 2 1 3 2 3 5 2 1 2 3 5 999 0 0
样例输出
-
1 0 2 998
上传者
- ACM_刘德强
-
-
#include<stdio.h> #include<string.h> int father[1005];//开数组 int find(int n)//写出查找函数 { return father[n]==n?n:find(father[n]); } int main() { int N,M; while(scanf("%d",&N)&&N)//多组数据N村庄 {scanf("%d",&M);//M道路 memset(father,0,1005);//数组清零 for(int i=1;i<=N;i++) father[i]=i;//令f[i]=i; for(int i=0;i<M;i++)//输入道路,判断是否联通,若不连通,,,; {int a,b; scanf("%d%d",&a,&b); int x=find(father[a]); int y=find(father[b]); if(x!=y) father[x]=y; } int count=-1; for(int i=1;i<=N;i++)//统计剩余断点; { if(father[i]==i) count++; } printf("%d\n",count); } } //输出;
-
测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
筹建工程
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本(道路是双向的)。现请你编写程序,计算出全省畅通需要的最低成本。
-
输入
-
测试输入包含若干测试用例。第一行一个整数 T (T <= 5) 表示测试用例数量,每个测
试用例的第 1 行给出评估的道路条数 N、村庄数目 M ( 1 <= M < 100,0 <= N <= M *( M-1) /2),随后的 N 行对应村庄间道路的成本,每行给出三个正整数,依次是两个村庄的编号(每对村庄至多出现一次),以及此两村庄间道路的成本( 也是正整数 )。
为简单起见,村庄从 1 到 M 编号。
输出
- 对每个测试用例,在 1 行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出 No solution。 样例输入
-
2 3 3 1 2 1 1 3 2 2 3 4 1 3 2 3 2
样例输出
-
3 No solution
来源
- 山东大学 ACM/ICPC 校赛高年级组试题 2012 上传者
- ACM_李如兵
-
测试输入包含若干测试用例。第一行一个整数 T (T <= 5) 表示测试用例数量,每个测
<pre name="code" class="cpp">
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;//头文件
int f[105]={0};//开数组
int find(int n)
{
return f[n]==n?f[n]:find(f[n]);//查找函数
}
struct mmd//结构体存储道路·价格
{
int a,b,mon;
}sz[5005];
int cmp(mmd a,mmd b)//cmp比较价格大小
{
return a.mon<b.mon;
}
int bmmd(int n,int m)//写出联通统计价格的函数;{f[i]=i;查找;判断联通}
{int sum=0;
int i=0;
for(i=1;i<=m;i++)
f[i]=i;
sort(sz,sz+n,cmp);
for( i=0;i<n;i++)
{
int x=find(sz[i].a);
int y=find(sz[i].b);
if(x!=y)
{
f[x]=y;
sum+=sz[i].mon;
}
}
return sum;
}
int main()
{
int r;
scanf("%d",&r);
while(r--)//T组数据
{memset(f,0,105);
int n,m;
int bg=0;
scanf("%d%d",&n,&m);
// printf("**%d%d\n",n,m);
for(int i=0;i<n;i++)
{//printf("****%d %d\n",i,n);
scanf("%d%d%d",&sz[i].a,&sz[i].b,&sz[i].mon);
}
for(int i=1;i<=m;i++)
f[i]=i;//令f[i]=i;
for(int i=0;i<n;i++)
{int x=0, y=0;
x=find(sz[i].a);//查找爸爸,判断是否联通,不连通使之联通
y=find(sz[i].b);
if(x!=y)
{
f[x]=y;
}
}
int count=-1;
for( int i=1;i<=m;i++)//查看断点个数;
{
if(f[i]==i)
count++;
}
if(count>0)//判断是否能联通;
printf("No solution\n");
else
printf("%d\n",bmmd(n,m));
}
}
//输出结果;