51nod魔法學校近日開展了主題爲“天氣晴朗”的魔法交流活動。
N名魔法師按陣法站好,之後選取N - 1條魔法鏈將所有魔法師的魔力連接起來,形成一個魔法陣。
魔法鏈是做法成功與否的關鍵。每一條魔法鏈都有一個魔力值V,魔法最終的效果取決於陣中所有魔法鏈的魔力值的和。
由於逆天改命的魔法過於暴力,所以我們要求陣中的魔法鏈的魔力值最大值儘可能的小,與此同時,魔力值之和要儘可能的大。
現在給定魔法師人數N,魔法鏈數目M。求此魔法陣的最大效果。
Input
兩個正整數N,M。(1 <= N <= 10^5, N <= M <= 2 * 10^5)
接下來M行,每一行有三個整數A, B, V。(1 <= A, B <= N, INT_MIN <= V <= INT_MAX)
保證輸入數據合法。
Output
輸出一個正整數R,表示符合條件的魔法陣的魔力值之和。
Input示例
4 6
1 2 3
1 3 1
1 4 7
2 3 4
2 4 5
3 4 6
Output示例
12
題面明確,構成一個連接連接所有點的樹.其中最大的邊儘可能小,在這個前提下,其他邊儘量大.
1: 最大的邊儘可能小,那麼可以用kurskal算法或者prim算法算法他的最小生成樹,記錄最大的那條邊。
2: 然後就知道,就算只選取小於這條邊的邊,也至少能構成1棵樹(最小生成樹),根據題目要求,優先選擇大的邊(但要小於1中記錄的最大值)
3: 很明顯這裏用kurskal更加的方便,因爲優先選擇大的邊,在一開始構成最小生成樹時已經排序好,記錄最大邊的位置,從尾到頭重新遍歷即可。
4:注意如果有邊和最大邊一樣長,也要記錄,還有就是sort語句的自定義排序語句,情況爲'=='時不能返回1,今天還特意問人查資料,具體原因自行百度補一波更清楚。
並查集不會的話,可以看我上一篇博客有我點一點理解。
我推薦一個視頻:http://www.bilibili.com/video/av8373130/
這是某大佬的教學,講的很好,吃個飯一邊看5分鐘,吃完就會並查集了。
然後 獻上代碼:
#include <iostream>
#include <cstdio>
#include <string.h>
#include <fstream>
#include <algorithm>
using namespace std;
long long int ans=0;
int fu[100005],i,j,n,m,gen1,gen2,maxbian=0,maxbnum;
struct bi
{
int from,to,leng;
}bian[200005];
int cmp1(bi a,bi b) //小的邊在前面
{
return a.leng<b.leng;
}
int cmp2(bi a,bi b) //大的在前面
{
return b.leng>a.leng;
}
int FindGen(int x) //路徑壓縮 查找
{
int a,b;
a=x;//保存初始值
while(fu[x]!=x)//找到根節點,而不是父節點
x=fu[x]; //得到根點x
//下面開始路徑壓縮
while(fu[a]!=x)//不是根的直接子點
{
b=fu[a];//保存父點,方便更改
fu[a]=x;
a=b;
}
return x;
}
int main()
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++) //父節點數組初始化
fu[i]=i;
for(i=0;i<m;i++)
scanf("%d%d%d",&bian[i].from,&bian[i].to,&bian[i].leng);
sort(bian,bian+m,cmp1);
for(i=0;i<m;i++)
{
gen1=FindGen(bian[i].from); //分別兩個點的根點
gen2=FindGen(bian[i].to);
if(gen1!=gen2) //根不同
{
fu[gen1]=gen2; //併合
if(bian[i].leng>maxbian)
{
maxbian=bian[i].leng;
maxbnum=i;
}
}
if(bian[i].leng==maxbian&&maxbnum!=i)//可能最大邊不止一條
maxbnum=i;
}
for(i=1;i<=n;i++) //父節點數組初始化
fu[i]=i;
for(i=maxbnum;i>=0;i--)
{
gen1=FindGen(bian[i].from); //分別兩個點的根點
gen2=FindGen(bian[i].to);
if(gen1!=gen2) //根不同
{
ans+=bian[i].leng;
fu[gen1]=gen2; //併合
}
}
printf("%lld",ans);
return 0;
}