题意:给出n个点,代表城市的个数,m代表给出的道路条数,k代表给出k组道路已经连通的,k行中的每一行首先给出城市个数t,后面跟上城市个数t,代表这t个城市任意两个城市之间已经是连通的,所以现在给出最小的修路费用。
方法一:Prim算法
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=505;
const int inf=0x3f3f3f3f;
int e[maxn][maxn];
int p[maxn];
int vis[maxn];
int dist[maxn];
int n,m,k;
int Prim(){
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++){
dist[i]=e[1][i];
p[i]=1;
}
dist[1]=0;
vis[1]=1;
int mincost=0;
for(int i=1;i<n;i++){
int temp=inf;
int t=-1;
for(int j=1;j<=n;j++){
if(!vis[j]&&dist[j]<temp){
temp=dist[j];
t=j;
}
}
if(t==-1)return -1;
vis[t]=1;
mincost+=dist[t];
for(int j=1;j<=n;j++){
if(e[t][j]<inf){
if(!vis[j]&&dist[j]>e[t][j]){
dist[j]=e[t][j];
p[j]=t;
}
}
}
}
return mincost;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d %d %d",&n,&m,&k);
for(int i=0;i<=n;i++){
dist[i]=inf;
for(int j=0;j<=n;j++){
e[i][j]=inf;
}
}
for(int i=0;i<m;i++){
int a,b,cost;
scanf("%d %d %d",&a,&b,&cost);
if(e[a][b]>cost){
e[a][b]=e[b][a]=cost;
}
}
int t[maxn];
int d;
for(int i=0;i<k;i++){
scanf("%d",&d);
for(int i=1;i<=d;i++){
scanf("%d",&t[i]);
}
for(int i=1;i<=d;i++){
for(int j=1;j<=d;j++){
if(i!=j){
e[t[i]][t[j]]=e[t[j]][t[i]]=0;
}
}
}
}
int mincost=Prim();
cout<<mincost<<endl;
}
return 0;
}
方法二:Kruskal算法-超时
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxx=1e5+10;
const int maxn=1005;
const int inf=0x3f3f3f3f;
int n,m,k;
int e[maxn][maxn];
int pre[maxx];
int ranks[maxx];
int vis[maxx];
struct node{
int u,v;
int w;
}num[maxx];
int cmp(node a,node b){
return a.w<b.w;
}
void init(){
for(int i=0;i<=maxx;i++){
pre[i]=i;
ranks[i]=0;
}
}
int find(int x){
if(pre[x]==x){
return x;
}
return pre[x]=find(pre[x]);
}
void unio(int x,int y){
int fx=find(x);
int fy=find(y);
if(ranks[fx]<ranks[fy]){
pre[fx]=fy;
}else{
pre[fy]=fx;
if(ranks[fx]==ranks[fy]){
ranks[fx]++;
}
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d %d %d",&n,&m,&k);
init();
for(int i=1;i<=m;i++){
scanf("%d %d %d",&num[i].u,&num[i].v,&num[i].w);
}
int b;
int p=0,d,r;
sort(num+1,num+m+1,cmp);
for(int i=0;i<k;i++){
scanf("%d %d",&d,&r);
for(int j=1;j<d;j++){
scanf("%d",&b);
int x=find(b);
int y=find(r);
if(x!=y){
unio(x,y);
++p;
}
}
}
int mincost=0;
for(int i=1;i<=m;i++){
int x=find(num[i].u);
int y=find(num[i].v);
if(x!=y){
mincost+=num[i].w;
unio(x,y);
++p;
}
if(p==n-1)break;
}
if(p==n-1){
cout<<mincost<<endl;
}else{
cout<<-1<<endl;
}
}
return 0;
}