对的代码:
#include <stdio.h>
#include <cstring>
#include <cmath>
#define INF 0xfffffff
#define max 105
double map[max][max],lowcost[max],sum;
bool visited[max];
struct coord{
double x,y;
}point[max];
double distance (coord a,coord b){ //a点与b点之间的距离
return sqrt ((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int Prime (int n){ //普利姆算法
int cnt=0;
double tmp;
memset (visited,0,sizeof (visited)); //所有节点的访问变量 初始化为假
visited[1] = true; //从第一个节点开始访问
sum = 0;
for (int i=1;i<=n;i++)
lowcost[i] = map[1][i];
for (int i=1;i<=n;i++){
tmp = INF;
int k=-1;
for (int j=1;j<=n;j++)
if (!visited[j] && lowcost[j] < tmp)
tmp = lowcost[k=j];
if (k==-1 || tmp == INF) break;
visited[k] = 1;
sum += tmp;
cnt++;
for (int i=1;i<=n;i++)
if (!visited[i] && map[k][i] < lowcost[i])
lowcost[i] = map[k][i];
}
// printf("cnt == %d\n",cnt);
return cnt;
}
int main (){
int t;
scanf ("%d",&t);
while (t--){
int n;
for (int i=1;i<=max;i++){ //所有岛之间距离初始化无穷大。
for (int j=i;j<=max;j++)
map[i][j] = map[j][i] = INF;
}
scanf ("%d",&n);
for (int i=1;i<=n;i++) //输入n个点的坐标
scanf ("%lf%lf",&point[i].x,&point[i].y);
for (int i=1;i<n;i++) //遍历所有可以修路的两个小岛
for (int j=i+1;j<=n;j++){
double tmp = distance(point[i],point[j]);
if (tmp <= 1000 && tmp >= 10)
map[i][j] = map[j][i] = tmp;
}
if (Prime (n) == n-1) //可以实现全部畅通
printf ("%.1lf\n",sum*100);
else
puts ("oh!");
}
return 0;
}
WA了n多次的代码:
#include <stdio.h>
#include <cstring>
#include <cmath>
#define INF 0xfffffff
#define max 105
double map[max][max],lowcost[max],sum;
bool visited[max];
struct coord{
double x,y;
}point[max];
double distance (coord a,coord b){
return sqrt ((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int Prime (int n){ //普利姆算法
int k=0,cnt=0;
double tmp;
memset (visited,0,sizeof (visited));
visited[1] = true;
sum = 0;
for (int i=1;i<=n;i++)
lowcost[i] = map[1][i];
for (int i=1;i<=n;i++){
tmp = INF;
for (int j=1;j<=n;j++)
if (!visited[j] && lowcost[j] < tmp)
tmp = lowcost[k=j];
if (tmp == INF) break;
visited[k] = 1;
sum += tmp;
cnt++;
for (int i=1;i<=n;i++)
if (!visited[i] && map[k][i] < lowcost[i])
lowcost[i] = map[k][i];
}
return cnt;
}
int main (){
int t;
scanf ("%d",&t);
while (t--){
int n;
memset (map,INF,sizeof (map)); //所有岛之间距离初始化无穷大。
scanf ("%d",&n);
for (int i=1;i<=n;i++) //输入n个点的坐标
scanf ("%lf%lf",&point[i].x,&point[i].y);
for (int i=1;i<n;i++) //遍历所有可以修路的两个小岛
for (int j=i+1;j<=n;j++){
double tmp = distance(point[i],point[j]);
if (tmp <= 1000 && tmp >= 10)
map[i][j] = map[j][i] = tmp;
}
if (Prime (n) == n-1) //可以实现全部畅通
printf ("%.1lf\n",sum*100);
else
puts ("oh!");
}
return 0;
}
对比两个代码其实就是主函数中对map赋值的地方不一样,结果就是完全相反。。我是在也不相信库函数了。
WA了n多次的并查集代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define max 105
struct Point{ // Coord
double x,y;
}point[max];
struct Node{
int a;
int b;
double cost;
}node[100010];
int cmp (const Node &a,const Node &b){
return a.cost < b.cost;
}
double dis (Point a,Point b){ // Distance
return sqrt ((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int bleg[max];
int find (int x){
int y = x;
while (y != x)
y = bleg[x];
while (x != bleg[x]){
int px = bleg[x];
bleg[x] = y;
x = px;
}
return y;
}
bool Union (int a,int b){
int pa = find(a),pb= find (b);
if (pa==pb) return false;
else
bleg[pa] = pb;
return true;
}
void init (int n){
for (int i=1;i<=n;i++) bleg[i] = i;
}
int main (){
int t;
scanf ("%d",&t);
while (t--){
int n,cnt=0,k=1;
scanf ("%d",&n);
init (n);
for (int i=1;i<=n;i++)
scanf ("%lf%lf",&point[i].x,&point[i].y);
for (int i=1;i<n;i++) //遍历出所有的可以联通的小岛
for (int j=i+1;j<=n;j++){
double tmp = dis (point[i],point[j]);
if (tmp >= 10 && tmp <= 1000){ //两岛之间的距离满足可以修路的条件
node[k].a=i;
node[k].b=j;
node[k++].cost=tmp;
}
}
k--; // k从1开始,所有最后要退一位。
sort (node+1,node+k+1,cmp); //按权值进行从下到大的排序
// for (int i=1;i<=k;i++)
// printf ("%.3lf\n",node[i].cost);
//----并查集部分
double sum = 0.0;
for (int i=1;i<=k;i++){
if (cnt==n-1) break;
if (Union (node[i].a,node[i].b)){
sum += node[i].cost; //累加权值
cnt++;
}
}
//printf ("cnt==%d\n",cnt);
if (cnt==n-1) //可以全部联通
printf ("%.1lf\n",sum * 100);
else
puts ("oh!");
}
return 0;
}