超级传送门:
http://acm.hdu.edu.cn/showproblem.php?pid=3371
//后面还是不写,等着写写个Prim+优先队列比较
题目分析:
是一道最小生成树的问题,不过,最后还给出了一大推已经连接好的点,所以要做一些小处理,
写了一个Prim+优先队列,超空间了,没有继续往下实验了。。。
下面是Prim的解法,上一个帖子是Kruskal的解法。。。
#include<iostream>
using namespace std;
const int inf = 900000000;
const int MAX_V = 510;
int map[MAX_V][MAX_V];
int n,m,k;
int f[MAX_V];
int dis[MAX_V];
int Prim()
{
int i,j;
int min,temp;
int sum = 0;
//初始化
for(i=1;i<=n;i++)
{
if(map[i][1] != -1)
{
dis[i] = map[i][1];
}
else
{
dis[i] = inf;
}
}
dis[1] = 0;
f[1] = 1;
//找最短的边
for(j=1;j<n;j++)
{
min = inf;
temp = 1;
for(i=1;i<=n;i++)
{
if(f[i] != 1 && dis[i] < min)
{
min = dis[i];
temp = i;
}
}
if(min == inf) break; //提前退出
//加入最小生成树
dis[temp] = min;
f[temp] = 1;
sum += min;
//跟新路径长度
for(i=1;i<=n;i++)
{
if(f[i] != 1 && map[i][temp] != -1 &&map[i][temp] < dis[i])
{
dis[i] = map[i][temp];
}
}
}
return sum;
}
int main()
{
int T;
int i,j;
int a,b,c;
int t,tt;
int p[MAX_V];
int ans;
scanf("%d",&T);
while(T--)
{
memset(map,-1,sizeof(map));
memset(f,0,sizeof(f));
memset(dis,0,sizeof(dis));
scanf("%d %d %d",&n,&m,&k);
for(i=0;i<m;i++)
{
scanf("%d %d %d",&a,&b,&c);
if(map[a][b] == -1 || map[a][b] > c)
{
map[a][b] = map[b][a] = c;
}
}
for(i=0;i<k;i++)
{
scanf("%d",&t);
for(j=0;j<t;j++)
{
scanf("%d",&p[j]);
}
for(j=0;j<t-1;j++)
{
for(tt=j+1;tt<t;tt++)
{
map[p[j]][p[tt]] = map[p[tt]][p[j]] = 0;
}
}
}
ans = Prim();
for(i=1;i<=n;i++)
{
if(dis[i] == inf) break;
}
if(i>n)
{
printf("%d\n",ans);
}
else
{
printf("-1\n");
}
}
return 0;
}