题目链接:http://acm.tju.edu.cn/toj/showp3073.html
题目大意:修路,要求任意两点之间都能到达,且花费最小,有的路已经修好了,求最小花费。
思路:很明显的MST问题 prim可解。注意两点:1、修好的路 权值设为0即可; 2、初始化时,点与点之间的距离设为无穷大,这里的无穷大只要比权值最大值大就行了,点到自身的距离设为0。(我就是因为一开始无穷大设的 0x7f ,一直wrong,不明觉厉,偶然改成1010就对了- -!)
顺便复习下prim吧:每次选取当前点到下一点距离最小的加入进来即可。唉,我表达的不太清楚,给个链接:http://blog.chinaunix.net/uid-25324849-id-2182922.html
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <limits.h>
using namespace std;
const int MAXN = 1003;
const int INF = 1010;
int n;
int visited[MAXN], dist[MAXN];
int map[MAXN][MAXN];
prim 模板
int prim()
{
int i,j,min, pos, sum;
for(i=1;i<=n;i++) //dist[]表示从相邻点到它的距离,初始化为从起点到各点的距离。
dist[i] = map[1][i];
visited[1] = 1;
for(i=0;i<n-1;i++) //小于n或n-1都可以 因为1已经放进去了 所以至少还要放n-1次
{
min = INF;
for(j=1;j<=n;j++)
if(!visited[j] && dist[j]<min) //找出下一步中距离最小的点。
{
min = dist[j];
pos = j;
}
visited[pos]=1;
for(j=1;j<=n;j++) //更新所有dist[]
if(!visited[j] && map[pos][j]<dist[j])
dist[j] = map[pos][j];
}
sum = 0;
for(i=1;i<=n;i++){ //若最后dist有无穷大,说明没有连通
sum+=dist[i];
if(dist[i]==INF) return -1;
}
return sum;
}
int main()
{
int cas,i,j,m,k,s,t,d;
cin>>cas;
while(cas--)
{
cin>>n>>m>>k;
memset(visited,0,sizeof(visited));
for(i=1;i<=n;i++) //初始化map
for(j=1;j<=n;j++){
if(i==j) map[i][j]=0;
else map[i][j]=INF;
}
for(i=0;i<m;i++)
{
cin>>s>>t;
map[s][t] = map[t][s] = 0; //无向图 要双向赋值
}
for(i=0;i<k;i++)
{
cin>>s>>t>>d;
map[s][t] = map[t][s] = d; //无向图 要双向赋值
}
cout<<prim()<<endl;
}
return 0;
}