题目链接
有N个村庄,从1到N,你应该修建一些道路,这样每两个村庄就可以连接起来。我们说两个村庄A和B相连,当且仅当A和B之间有一条路,或者存在一个村庄C使得A和C之间有一条路,并且C和B相连。我们知道一些村庄之间已经有一些道路了,你的工作是修建一些道路,这样所有的村庄都连接起来,所有道路的长度都是最小的。
Input
第一行是整数N (3 <= N <= 100),即村庄数。然后是N行,第i行包含N个整数,第j列是村i和村j之间的距离(距离应该是[1,1000]内的整数)。然后是整数Q (0 <= Q <= N * (N + 1) / 2),然后是Q行,每一行包含两个整数a和b (1 <= a < b <= N),这意味着a村和b村之间的道路已经建成。
Output
您应该输出一条包含整数的线,该整数是所有要修建的道路的长度,以便所有村庄都连接起来,并且该值是最小的。
Sample Input
3
0 990 692
990 0 179
692 179 0
1
1 2
Sample Output
179
详见代码:
```cpp
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define inf 0x3f3f3f3f
//const int inf=0x3f3f3f3f;
int n;
int mp[105][105],dis[105];
//int vis[105];
bool vis[105];//0为false,1为true。
void Prim()
{
int v,mi;
/*for(int i=2;i<=n;i++)
{
dis[i]=mp[1][i];
//vis[i]=1;
vis[i]=false;
}*/
for(int i=1;i<=n;i++)
{
dis[i]=mp[1][i];//先把1加入Vnew,若给出1到与1相连的点,则dis就是给出的输入的mp[1][i],否则就是inf
vis[i]=false;
}
//vis[1]=0;
//vis[1]=true;
//dis[1]=0;
int sum=0;
//for(int i=1;i<=n-1;i++)
for(int i=1;i<=n;i++)
{
mi=inf;
for(int j=1;j<=n;j++)
//if(mi>dis[j]&&vis[j]!=0)
if(!vis[j]&&mi>dis[j])//在集合V中先找出一个没有加入集合Vnew的&&权值最小的点
{
mi=dis[j];
v=j;//v先后等于1,2,3
}
vis[v]=true;//标记该点已经加入Vnew
dis[v]=0;//路已经修好,距离更新为0
sum+=mi;
for(int j=1;j<=n;j++)
{
/*if(dis[j]>dis[v]+mp[v][j])
{
dis[j]=dis[v]+mp[v][j];
vis[j]=v;
}*/
if(!vis[j]&&dis[j]>mp[v][j])//如果这个点没有加入Vnew还在V中&&
{
dis[j]=mp[v][j];
}
}
}
printf("%d\n",sum);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
//mp[i][j]=mp[j][i]=(i==j)?0:inf;
{
if(i==j)
mp[i][j]=mp[j][i]=0;
else
mp[i][j]=mp[j][i]=inf;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&mp[i][j]);
int q;
scanf("%d",&q);
while(q--)
{
int a,b;
scanf("%d%d",&a,&b);
mp[a][b]=mp[b][a]=0;
}
Prim();
return 0;
}