最近在准备保研的机试题,从最开始什么都不会,到现在可以写出来一些简单的题,这也算一个成长嘛,本科期间除了上课,做了几个项目,没怎么接触算法的东西。如果有大一二的学妹学弟,如果有机会一定要参加参加ACM我觉得真的百利而无一害。我其实写了挺多题了,只是都是写在自己的印象笔记里,感觉还是可以写个博客集合。直接看下面的题吧。
九度http://ac.jobdu.com/problem.php?pid=1012
牛客
https://www.nowcoder.com/practice/4878e6c6a24e443aac5211d194cf3913tpId=63&tqId=29573&tPage=1&ru=%2Fkaoyan%2Fretest%2F9001&qru=%2Fta%2Fzju-kaoyan%2Fquestion-ranking
解题:http://blog.csdn.net/thudaliangrx/article/details/49182821
思路:
典型的最小生成树问题。通常有两种方法,Prim算法和Kruskal算法。
两种方法分别更适合于稠密图和稀疏图,个人比较喜欢用后一种方法,通常在算法实现上需结合并查集。
两种算法介绍可参考博客:
http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html
我的代码:
#include<iostream>
#include<set>
using namespace std;
//int a[1001][1001];
int b[1001];
int main(){
int n,m;
set<int> se;
while(cin>>n>>m && n!=0){
for(int j=1;j<=n;j++){
b[j]=0;
}
int from,to;
for(int i=0;i<m;i++){
cin>>from>>to;
if(b[from]== 0 && b[to]==0){
b[from]=b[to]=from;
}else if(b[from] ==0 && b[to]!=0){
b[from]=b[to];
}else if(b[from] !=0 && b[to]==0) {
b[to]=b[from];
}else if(b[from] !=0 && b[to]!=0 && b[from]!=b[to]){
int te=b[to];
for(int i=1;i<=n;i++)
if(b[i] == te)
b[i]=b[from];
}
}
int count=0;
//int i;
for( int i=1;i<=n;i++){
if(b[i] != 0) se.insert(b[i]);
else count++;
// cout<<b[i]<<" ";
}
//cout<<endl;
cout<<se.size()+count-1<<endl;
se.clear();
}
return 0;
}
解题答案:
#include <stdio.h>
#define M 1000
int count = 0;
int id[M+1];
void UF(int n)
{
for (int i=1; i<=n; i++)
id[i] = i;
}
int find(int i)
{
return id[i];
}
void combine(int i, int j, int n)
{
int a = find(i);
int b = find(j);
if (a == b)
return ;
for (int k=1; k<=n; k++)
{
if (id[k] == a)
id[k] = b;
}
count--;
}
int main(void)
{
int m, n;
int a, b;
int i;
while (scanf("%d", &n) != EOF && n)
{
scanf("%d", &m);
count = n;
UF(n);
for (i=0; i<m; i++)
{
scanf("%d%d", &a, &b);
combine(a, b, n);
}
printf("%d\n", count-1);
}
return 0;
}