标签:
1 6 4 3 1 4 2 2 6 1 2 3 5 3 4 33 2 1 2 2 1 3 3 4 5 6
1
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3371
题意:由于海平面上升,有一些城市消失了,有些城市间还有相连,但更多的城市间的已经不相连了,现在政府要修建一些路,使得所有的城市都相连,问你将所有城市连接起来还要花费多少钱。
输入n,m,k,分别代表城市总数,可修建的路的条数,现在任然连接的城市数。
接下来的m行各有三个数,分别代表两个城市间修路的费用,
最后k行,每行第一个数字 t 代表后面的 t 个城市仍然相连。
一看就知道是最小生成树,但有点改动,因为有一部分已经相连。再用Kruskal算法的时候把还相连的城市用并查集连在一起,而用Prime算法的把还相连的城市之间的修路的费用记为0就可以了。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
struct node
{
int s,e,w;
} a[25000+5];
int n,m,k;
int fa[505];
bool cmp(node a,node b)
{
return a.w<b.w;
}
int Find(int x)
{
if(fa[x]==x)
return x;
return fa[x]=Find(fa[x]);
}
int Kruskal()
{
sort(a+1,a+m+1,cmp);
int ans=0;
for(int i=1; i<=m; i++)
{
int x=Find(a[i].s);
int y=Find(a[i].e);
if(x!=y)
{
ans+=a[i].w;
fa[x]=y;
}
}
return ans;
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n>>m>>k;
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&a[i].s,&a[i].e,&a[i].w);
}
for(int i=1; i<=n; i++)
fa[i]=i;
for(int i=1; i<=k; i++)
{
int t,x,y;
scanf("%d%d",&t,&x);
for(int j=2; j<=t; j++)
{
scanf("%d",&y);
int fx=Find(x);
int fy=Find(y);
if(fx!=fy)
fa[fx]=fy;
}
}
int ans=Kruskal();
int sum=0;
for(int i=1; i<=n; i++)
{
if(fa[i]==i)
sum++;
}
if(sum>1)
cout<<"-1"<<endl;
else
cout<<ans<<endl;
}
return 0;
}#include <cstdio>
#include <cstring>
using namespace std;
int a[505][505];
int dis[505];
bool vis[505];
int t[505];
const int INF=0x3f3f3f3f;
int n,m,k;
int Prime()
{
for(int i=1; i<=n; i++)
{
vis[i]=false;
dis[i]=a[1][i];
}
vis[1]=true;
dis[1]=0;
int ans=0;
for(int i=1; i<n; i++)
{
int minn=INF;
int p=-1;
for(int j=1; j<=n; j++)
{
if(!vis[j]&&dis[j]<minn)
minn=dis[p=j];
}
vis[p]=true;
if(p==-1)
return -1;
ans+=minn;
for(int j=1; j<=n; j++)
{
if(!vis[j]&&dis[j]>a[p][j])
dis[j]=a[p][j];
}
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(i==j) a[i][j]=0;
else a[i][j]=INF;
}
}
int x,y,z;
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&x,&y,&z);
if(z<a[x][y])
a[x][y]=a[y][x]=z;
}
while(k--)
{
scanf("%d",&x);
for(int i=1; i<=x; i++)
{
scanf("%d",&t[i]);
}
for(int i=1; i<x; i++)
{
for(int j=i+1; j<=x; j++)
a[t[i]][t[j]]=a[t[j]][t[i]]=0;
}
}
printf("%d\n",Prime());
}
return 0;
}
HDU 3371 Connect the Cities 【最小生成树,Prime算法+Kruskal算法】
标签:
原文地址:http://blog.csdn.net/hurmishine/article/details/52108142