1. 程式人生 > >luoguP1195 口袋的天空 x

luoguP1195 口袋的天空 x

現在 生成 bool 通過 窗戶 col 輸出格式 sky cin

P1195 口袋的天空

    • 378通過
    • 867提交
  • 題目提供者該用戶不存在
  • 標簽 雲端
  • 難度 普及+/提高
  • 時空限制 1s / 128MB

題目背景

小杉坐在教室裏,透過口袋一樣的窗戶看口袋一樣的天空。

有很多雲飄在那裏,看起來很漂亮,小杉想摘下那樣美的幾朵雲,做成棉花糖。

題目描述

給你雲朵的個數N,再給你M個關系,表示哪些雲朵可以連在一起。

現在小杉要把所有雲朵連成K個棉花糖,一個棉花糖最少要用掉一朵雲,小杉想知道他怎麽連,花費的代價最小

輸入輸出格式

輸入格式:

每組測試數據的

第一行有三個數N,M,K(1<=N<=1000,1<=M<=10000,1<=K<=10)

接下來M個數每行三個數X,Y,L,表示X雲和Y雲可以通過L的代價連在一起。(1<=X,Y<=N,0<=L<10000)

30%的數據N<=100,M<=1000

輸出格式:

對每組數據輸出一行,僅有一個整數,表示最小的代價。

如果怎麽連都連不出K個棉花糖,請輸出‘No Answer‘。

輸入輸出樣例

輸入樣例#1:
3 1 2
1 2 1
輸出樣例#1:
1

說明

廈門一中YMS原創

思路:

  首先要想明白題目讓你做什麽:

          更改成通俗的話就是將n個點再添加上幾條邊之後變為k個點,並且使得連邊的花費達到最小

  那麽就很明白啦~如下圖:

技術分享技術分享

  想要將8個點,變為3個點,所以需要搞一個最小生成樹,將與其他邊相連時邊權較小的6個點連起來,如下圖:

技術分享

  然後 通過大量的實驗可以的證:

技術分享

  只需要搞一個點數為n-k的最小生成樹即可成功

上代碼:

#include <algorithm>
#include <iostream>
using namespace std;

const int INF = 0x7fffffff;
const int N = 1010;
const int M = 10010;
int n,m,k,ans,cnt;
int
dad[N]; struct Sky { int u,v,w; bool operator < (const Sky &qwq)const { return w < qwq.w; } }s[M]; int getdad(int x) {return dad[x] == x ? x : dad[x] = getdad(dad[x]);} void kruskal() { for(int i=1;i<=n;i++) dad[i]=i; sort(s+1,s+1+m); for(int i=1;i<=m;i++) { int f1=getdad(s[i].u),f2=getdad(s[i].v); if(f1!=f2) { dad[f1]=f2; ans+=s[i].w; cnt++; } if(cnt==k)//此時的k為輸入的n-k break; } if(cnt<k) { cout<<"No Answer";//其實這個去掉也可以,因為沒有數據搞這裏... return; } cout<<ans; } void add(int b,int u,int v,int w) {s[b].u=u,s[b].v=v,s[b].w=w;} int main() { cin>>n>>m>>k; k=n-k;//直接先把k變為n-k for(int i=1,x,y,l;i<=m;i++) { cin>>x>>y>>l; add(i,x,y,l); } kruskal(); return 0; }

luoguP1195 口袋的天空 x