Codevs 2796 最小完全圖
阿新 • • 發佈:2017-05-13
ret smart 端點 val cmp ble scanf sin else
輸出描述 Output Description
2796 最小完全圖
http://codevs.cn/problem/2796/
題目描述 Description若一個圖的每一對不同頂點都恰有一條邊相連,則稱為完全圖。
最小生成樹MST在Smart的指引下找到了你,希望你能幫它變成一個最小完全圖(邊權之和最小的完全圖)。
註意:必須保證這個最小生成樹MST對於最後求出的最小完全圖是唯一的。
輸入描述 Input Description第一行一個整數n,表示生成樹的節點數。
接下來有n-1行,每行有三個正整數,依次表示每條邊的頂點編號和邊權。
(頂點的邊號在1-n之間,邊權<231)
一個整數ans,表示以該樹為最小生成樹的最小完全圖的邊權之和。
樣例輸入 Sample Input4
1 2 1
1 3 1
1 4 2
樣例輸出 Sample Output12
數據範圍及提示 Data Size & Hint30%的數據:n<1000;
100%的數據:n≤20000,所有的邊權<2^31。
/* 樹就是不存在環的圖,而完全圖就要求我們把樹上的點間關系全部變成環 首先把各邊從小到大排序,以保證從小的開始,結果更優 以樹上的每條邊為基底,進行合並 比如用到邊i,其端點為a,b 將b所在的樹合並到a所在的樹上,也就是要求兩棵小樹中所有的點構成一個小的完全圖 那麽從b樹上所有點都向a圖上所有點連一條長為v[i]+1的線即可,這樣的線一共有siz[a]*siz[b]-1條 上式中"-1"代表的那條邊就是邊i,其邊權為v[i] 就這樣跑完最小生成樹的所有邊,同時將邊權累加即可 最後提醒 所有的邊權<2^31,別忘了用long long*/ #include<iostream> #include<cstdio> #include<algorithm> using namespace std; long long siz[20010],n,ans,father[20010]; struct node{ long long from,to,v; }e[20010]; long long find(long long a){ if(father[a]==a)return father[a]; else return father[a]=find(father[a]); }long long cmp(node a,node b){ return a.v<b.v; } int main(){ scanf("%d",&n); for(long long i=1;i<n;i++)scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].v); for(long long i=1;i<=n;i++)father[i]=i,siz[i]=1; sort(e+1,e+n,cmp); for(long long i=1;i<n;i++){ long long a=e[i].from,b=e[i].to; long long f1=find(a),f2=find(b); father[f2]=f1; ans+=e[i].v; long long value=siz[f1]*siz[f2]-1; ans+=value*(e[i].v+1); siz[f1]+=siz[f2];//與19行對應,註意是誰變成了誰的子樹 } cout<<ans; }
Codevs 2796 最小完全圖