洛谷P1195 口袋的天空
并查集
将边从小到大排序,然后依次加边 看看是否能变成 K 个连通块,
以及其最小话费
1 #include <cstdio> 2 #include <algorithm> 3 #define For(i,j,k) for(int i=j;i<=k;i++) 4 using namespace std ; 5 6 const int N = 1011,M = 10011,inf = 1e9 ; 7 struct edge{ 8 int x,y,val ; 9 }e[M] ; 10 11 int n,m,k,sum,num ; 12 int fa[N] ; 13 14 inline int read() 15 { 16 int x = 0 , f = 1 ; 17 char ch = getchar() ; 18 while(ch<'0'||ch>'9') { if(ch=='-') f = -1 ; ch = getchar() ; } 19 while(ch>='0'&&ch<='9') { x = x * 10+ch-48 ; ch = getchar() ; } 20 return x * f ; 21 } 22 23 inline bool cmp(edge a,edge b) 24 { 25 return a.val < b.val ; 26 } 27 28 inline int find(int x) 29 { 30 if(fa[x]==x) return x ; 31 return fa[ x ] = find(fa[x]) ; 32 } 33 34 inline void work() 35 { 36 int x,y ; 37 num = 0 ; sum = 0 ; 38 sort(e+1,e+m+1,cmp) ; 39 For(i,1,m) { 40 x = find(e[ i ].x) ; 41 y = find(e[ i ].y) ; 42 if(x!=y) { 43 num++ ; sum+=e[ i ].val ; 44 if(num==n-k) { 45 printf("%d ",sum) ; 46 return ; 47 } 48 fa[x] = y ; 49 } 50 } 51 printf("No Answer ") ; 52 } 53 54 int main() 55 { 56 while(~scanf("%d%d%d",&n,&m,&k)) { 57 For(i,1,n) fa[ i ] = i ; 58 For(i,1,m) { 59 e[ i ].x = read() ; e[ i ].y = read() ; e[ i ].val = read() ; 60 } 61 work() ; 62 } 63 return 0 ; 64 }