题目描述
在有向图G中,如果两个顶点u,v间有一条从u到v的有向路径,同时还有一条从v到u的有向路径,则称两个顶点强连通。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向非强连通图的极大强连通子图,称为强连通分量。 不连通的单个的点也被称为一个强连通分量
现有一个n个点m条双向边的图,每条边有一个权值L,从m条边中选出若干条,形成一个含有k个强连通分量的图且选用的边的权值和最小
输入描述
第一行:输入三个数n、m、k,分别表示n个点,m条边,形成含有k个强连通分量的图
接下来m行:每行输入三个数,x、y、L,表示x和y之间有一条权值为L的双向边
对于 30% 的数据: n ≤ 100 m ≤ 1000 L ≤ 10000
对于100%的数据: n ≤ 1000 m ≤ 10000 L ≤ 10000
输出描述
如果可以形成含有k个强连通分量的图,输出选用边的权值和的最小值
如果不能形成则输出“ No Answer”
样例
输入
3 1 2 1 2 1
输出
1
讲解
因为这道题是要求找到最小的权值和,所以这道题一定是某种求最小值的算法
且这个只要联通就行,无需成圈,所以是棵树
就是最小生成树
因为要分为K部分所以是K棵最小生成树
下面为代码
#include<cstdio>
#include<algorithm>
using namespace std;
struct node{
int x,y,l;
}a[10005];
//排序
bool cmp(const node a,const node b){
return a.l<b.l;
}
int f[1005];
int n,m,k,cnt,sum;
//并查集的查找
int find(int x){
if(x==f[x])
return x;
return f[x]=find(f[x]);
}
//并查集的初始化
void init(){
for(int i=1;i<=1000;i++)
f[i]=i;
}
//最小生成树
void kruskal(){
sort(a+1,a+1+m,cmp);
for(int i=1;i<=m;i++){
int x=find(a[i].x),y=find(a[i].y);
if(x==y)
continue;
sum+=a[i].l;
cnt++;
f[x]=y;
if(cnt==n-k)
break;
}
if(n-k==cnt)
printf("%d",sum);
else
puts("No Answer");
}
int main(){
scanf("%d%d%d",&n,&m,&k);
init();
//读入
for(int i=1;i<=m;i++)
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].l);
kruskal();
return 0;
}