1. 程式人生 > >51nod 1640 天氣晴朗的魔法 (最小生成樹)

51nod 1640 天氣晴朗的魔法 (最小生成樹)

sam out 生成樹 魔法 space int 與此同時 names 算法題

1640 天氣晴朗的魔法技術分享 題目來源: 原創 基準時間限制:1 秒 空間限制:131072 KB 分值: 20 難度:3級算法題 技術分享 收藏 技術分享 關註 技術分享 取消關註
這樣陰沈的天氣持續下去,我們不免擔心起他的健康。
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


分析:要求陣中的魔法鏈的魔力值最大值盡可能的小,那麽最小會小到什麽程度呢?最小也不會比用最小生成樹算法求得的樹中的最大權值小。
所以,這個題用最小生成樹算法求出最大權值後,再求有限制的最大生成樹即可。

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxe=200005;

const int maxv=100005;
int V,E;
struct edge
{
int u,v,cost;
};
edge es[maxe];
int par[maxv];
void init(int n)
{
for(int i=1;i<=n;i++)
{
par[i]=i;
}
}
int find(int x)
{
if(par[x]==x) return x;
else return par[x]=find(par[x]);
}
bool same(int x,int y)
{
return find(x)==find(y);
}
void unit(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx==fy) return ;
else
{
par[fx]=fy;
}
}
bool cmp1(const edge& e1,const edge& e2)
{
return e1.cost<e2.cost;
}
bool cmp2(const edge& e1,const edge& e2)
{
return e1.cost>e2.cost;
}
int kur_maxv()
{
init(V);
sort(es,es+E,cmp2);
int ans=-1;
for(int i=E-1;i>=0;i--)
{
if(!same(es[i].u,es[i].v))
{
unit(es[i].u,es[i].v);
int tmp=es[i].cost;
if(tmp>ans || ans==-1)
ans=tmp;
}
}
return ans;
}
int main()
{
scanf("%d%d",&V,&E);
ll ans=0;
for(int i=0;i<E;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
es[i].u=x;
es[i].v=y;
es[i].cost=z;
}
int maxcost=kur_maxv();
init(V);
for(int i=0;i<E;i++)
{
if(!same(es[i].u,es[i].v) && es[i].cost<=maxcost)
{
unit(es[i].u,es[i].v);
ans+=es[i].cost;
}
}

printf("%lld\n",ans);
return 0;
}

 

51nod 1640 天氣晴朗的魔法 (最小生成樹)