P1195 口袋的天空
链接:P1195
------------------------------
这道题第一眼肯定能想到最小生成树,不过最小生成树最后就成了一个连通块。
哎,最后?我们想一下卡鲁斯卡尔算法,是一次加上一条边,而且这边的两端不再一个联通块中。
也就是说,我们的每一次操作,就相当于消除了一个连通块。
这样,我们在最后留下k个联通块不就可以了?
-----------------------------
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 int p; 6 struct b{ 7 int f; 8 int to; 9 int v; 10 }bian[10500]; 11 int n,m,k; 12 int fa[105000]; 13 int find(int x){ 14 if(x==fa[x]) 15 return x; 16 else 17 return fa[x]=find(fa[x]); 18 } 19 int on(int x,int y){ 20 int x1=find(x); 21 int y1=find(y); 22 if(x1!=y1) 23 fa[x1]=y1; 24 } 25 bool cmp(b a,b c){ 26 return a.v<c.v; 27 } 28 int x,y,l; 29 int ans; 30 int main(){ 31 cin>>n>>m>>k; 32 for(int i=1;i<=m;++i){ 33 scanf("%d%d%d",&x,&y,&l); 34 p++; 35 bian[p].f=x; 36 bian[p].to=y; 37 bian[p].v=l; 38 } 39 for(int i=1;i<=n;++i) 40 fa[i]=i; 41 if(m!=1) 42 sort(bian+1,bian+1+m,cmp); 43 int k1=n-k; 44 int flag=1; 45 while(k1){ 46 int u=bian[flag].f; 47 int v=bian[flag].to; 48 if(find(u)!=find(v)){ 49 k1--; 50 ans+=bian[flag].v; 51 on(u,v); 52 } 53 flag++; 54 } 55 cout<<ans; 56 return 0; 57 }