構造完全圖(G)解題報告


題目描述

對於完全圖 G,若有且僅有一棵最小生成樹為 T,則稱完全圖 G 是樹 T 擴展出的。

給你一棵樹 T,找出 T 能擴展出的邊權和最小的完全圖 G。

輸入格式

第一行 N 表示樹 T 的點數;

接下來 N−1 行三個整數 Si,Ti,Dii​​,Ti​​,Di​​;描述一條邊(Si,TiS_i, T_iSi​​,Ti​​)權值為 DiD_iDi​​;

保證輸入數據構成一棵樹。

輸出格式

輸出僅一個數,表示最小的完全圖 G 的邊權和。

樣例

樣例輸入

4  
1 2 1  
1 3 1  
1 4 2

樣例輸出

12

樣例說明

添加 D(2,3)=2,D(3,4)=3,D(2,4)=3D(2, 3)=2, D(3, 4)=3, D(2, 4)=3D(2,3)=2,D(3,4)=3,D(2,4)=3 即可。

題目鏈接:https://loj.ac/problem/10067

解題思路:首先完全圖是指每兩個點之間都有連邊的圖,題目是要求一個邊權和最小的完全圖,

題目給出的是一個最小生成樹,我們可以從邊入手,把每條邊所連的左右兩個點分別看做一個集合,

左邊集合和右邊集合所要連的邊數是(cnt[i]*cnt[j]-1),我們要連的邊權是多大?不能比當前的邊還小,

那么就不滿足有且僅有一棵最小生成樹T,所以邊權就為(當前邊的邊權+1),我們可以貪心的去解決,

把邊從小到大排序,並查集一下就行了,當然還得加上原始邊的邊權。

 

代碼如下:

 

#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm>
#define ll long long int
using namespace std; struct T{ ll u,v,w; }t[100005]; ll ans,n,cnt[100005],fa[100005]; ll find(ll x){ if(fa[x]!=x) return fa[x]=find(fa[x]); else
    return fa[x]; } bool cmp(T a,T b){return a.w<b.w;} int main(){ scanf("%lld",&n); for(ll i=1;i<=n-1;i++) scanf("%lld%lld%lld",&t[i].u,&t[i].v,&t[i].w),ans+=t[i].w; for(ll i=1;i<=n;i++){ fa[i]=i;cnt[i]=1; } sort(t+1,t+n,cmp); for(ll i=1;i<=n-1;i++){ ll r1=find(t[i].u); ll r2=find(t[i].v); if(r1!=r2){ ans+=(cnt[r1]*cnt[r2]-1)*(t[i].w+1);
            fa[r2]=r1; cnt[r1]+=cnt[r2]; } } printf("%lld",ans); return 0; }

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM