[タイトル]イタリア
得られる\(N(N <= 100 )\) 図ノード、できるだけ小さいエッジにまたがる最大マイナス最小エッジを求めるを。
[アルゴリズム]
\(クラスカル\)
[分析]
まず、サイド・バイ・サイド右側の小から大規模なソートします。エッジ間隔の連続したセットについて\([L、R&LT] \)エッジ場合ように、\(N- \)ポイント全てユニコム、次に細い以下ではありません\(W [R] -W [ L]は\) (スパニングツリー\(W [i]とは、\)ソート表す\(Iは\)エッジの重量)。
列挙昇順\(Lの\)のそれぞれについて、\(Lの\)小から大列挙に、\(R&LTの\)検索の新しいセットを使用している間、及び入力\([L、R] \ ) エッジの両端の点が一組にマージ、および\(クラスカル\)同じアルゴリズム。全ての点がユニコム停止列挙されている場合\(R&LTの\)を、置換\(Lの\)を(及び\(R&LTの\は)にリセットされる(Lの\)\)列挙を続行します。
[コード]
#include<bits/stdc++.h>
using namespace std;
const int MAXN=100+10;
const int MAXM=10000+10;
int n,m;
int fa[MAXN];
int maxn,ans=0x3f3f3f3f;
struct Node
{
int u,v,w;
}edge[MAXM];
inline int read()
{
int tot=0;
char c=getchar();
while(c<'0'||c>'9')
c=getchar();
while(c>='0'&&c<='9')
{
tot=tot*10+c-'0';
c=getchar();
}
return tot;
}
inline bool cmp(Node x,Node y)
{
return x.w<y.w;
}
inline int find(int k)//并查集
{
if(fa[k]==k)return k;
else return fa[k]=find(fa[k]);
}
inline bool kruskal(int k)//判断是否能形成生成树
{
maxn=0;
int tot=0;
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=k;i<=m;i++)
{
if(fa[find(edge[i].u)]!=fa[find(edge[i].v)])
{
maxn=edge[i].w;
fa[find(edge[i].u)]=fa[find(edge[i].v)];
tot++;
}
if(tot==n-1)return 1;//如果所有点都联通,则返回true
}
return 0;//否则返回false
}
int main()
{
while(1)
{
ans=0x3f3f3f3f;
n=read();m=read();
if(!n&&!m)break;
for(int i=1;i<=m;i++)
{
edge[i].u=read();
edge[i].v=read();
edge[i].w=read();
}
sort(edge+1,edge+1+m,cmp);//给边进行从小到大排序
for(int i=1;i<=m;i++)//枚举L
{
if(kruskal(i))
{
ans=min(ans,maxn-edge[i].w);//更新最小值
}
}
if(ans!=0x3f3f3f3f)cout<<ans<<endl;
else cout<<-1<<endl;//特判
}
return 0;
}
劉Rujia大法が良いです!