Judge Info
- Memory Limit: 32768KB
- Case Time Limit: 10000MS
- Time Limit: 10000MS
- Judger: Number Only Judger
Description
Actually, Mr.K is a famous engineer. He got a big project resently.He is asked to build roads to connect several city. At first, there is no roads between any pair of these city. He is given the distances between any two cities . Mr.K wants to build roads as less length as posible to make all city connected.
Input
The input will contains multiple test cases. The first line of the input is a single integer which is the number of test cases. T test cases follow.
Each test case contains one positive integers --the number of the citis numbered 1 to n. Next,there are n rows, and which row contains n positive integer. The integer at ith row,jth column is the distance between city i and city j, and it will never bigger than 10,000;
Output
For each input test case, you are to output a single integer - the smallest length of roads that make all cities connected.
Sample Input
2 3 0 1 1 1 0 2 1 2 0 3 0 1 1 1 0 2 1 2 0
Sample Output
2
#include <algorithm>
#include <iostream>
using namespace std;
const int INF = 0x7F800000; // 无穷大
const int MAX = 1000+5;
int mtx[MAX][MAX];//用来储存图边权的邻接矩阵
int dist[MAX];
int main()
{
int t,n,i,j,k;
scanf("%d",&t);
for (i=1;i<=t;i++)
{
scanf("%d",&n);
for (j=1;j<=n;j++)
{
for (k=1;k<=n;k++)
{
scanf("%d",&mtx[j][k]);
}
}
for (j=1;j<=n;j++) //创建第一组dist
{
if ( (mtx[1][j])!=0 || (j==1) )
dist[j]=mtx[1][j]; //如果节点i能够与start节点直接相连,则dist[i]赋值为他们的直接距离
else
dist[j]=INF; //否则赋值为无穷大
}
int ans=0;
for (k=2;k<=n;k++) //不断更新dist
{
int minEdge=INF,minpoint; // minEdge记录当前往外扩展的最小非零边权,minPoint记录对应边指向的节点编号
for (j=1;j<=n;j++) //不断更新dist
{
if (dist[j]!=0 && dist[j]<minEdge) //找到最小加权边与点
{
minEdge=dist[j];
minpoint=j;
}
}
dist[minpoint]=0; //将当前节点标记为已加入生成树,dist值置零
ans+=minEdge; //累计生成树的路径长度
for (j=1;j<=n;j++) 用此节点一一跟新其他点的dist值
{
if (mtx[minpoint][j]<dist[j]&&mtx[minpoint][j]!=0)
dist[j]=mtx[minpoint][j];
}
}
printf("%d\n",ans);
}
return 0;
}
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
int f[1004];
int find(int x) //x所在集合的根
{
if(x==f[x])return x;
return f[x]=find(f[x]);
}
struct aaaa
{
int u,v;
int weight;
};
aaaa edge[500004];
bool cmp(aaaa a,aaaa b)
{
return (a.weight<b.weight);
}
int main()
{
int t,n,i,j,k,pp;
scanf("%d",&t);
for (i=1;i<=t;i++)
{
scanf("%d",&n);
for(int j=1;j<=n;j++) f[j]=j; //初始化为自己**********************
int ko=1;
for (j=1;j<=n;j++)
{
for (k=1;k<=n;k++)
{
if (k<j+1) scanf("%d",&pp);
if (k>=j+1)
{
edge[ko].u=j;
edge[ko].v=k;
scanf("%d",&edge[ko].weight);
ko++;
}
}
}
sort(edge+1,edge+n*(n-1)/2+1,cmp);
int z1=1;
int z=0;
for (j=1;j<=((n-1)*n/2);j++)
{
int sb=find( f[edge[j].v] ); //找根
int sa= find( f[edge[j].u] ); //找根
if ( sa!=sb )
{
f[sb]=sa; //关键**是把两集合的跟并在一起。而不是一个元素和另一个集合根并在一起
//之前一直没AC是因为 f[edge[j].v]=find(f[edge[j].u]); 导致没真正并
z+=edge[j].weight;
if (z1>=(n-1)) break;
}
}
printf("%d\n",z);
}
return 0;
}