我是靠谱客的博主 贪玩银耳汤,最近开发中收集的这篇文章主要介绍PTA-最小生成树的唯一性-(最小生成树的边权地位),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

最小生成树的唯一性

题意:
就是给你n点个m条边,问你是否能这个图的最小生成树是唯一的,如果唯一输出最小生成树的权值,不唯一输出一共有多少连通块。

思考:
其实乍一看判断最小生成树是否唯一感觉像是见过,但是怎么也想不到,那就是没做过,只是见过罢了。然后我就想,是否唯一该怎么判断呢,之前做过两道都是用最小生树相同边权的地位都是相同的性质,我感觉如果在合并之前有res个边需要用,但是到了合并的时候只有res_t个了,也就是某些边可以用可以不用,只要出现这种情况那么这个最小生成树就不是唯一的。其余的操作就很简单了。对于这个想法的证明我没想到,我想了几组数据都没hack掉。如果要hack话,我感觉这个方法可以hack的地方就是这个图的最小生成树是否唯一不是在相同的边权上产生的,而是一大一小之类的。对了,这个PTA有个坑的地方就是,有的换行不知道到底输出还是不输出…。
2022-4-6,对于POJ的The Unique MST这道题,这个算法也是对的。之前是因为我把遍历边的时候m写成n了,今天刚发现,太绝绝子了。
这个判断最小生成树是否唯一是第一发现这种做法耶,我命名为美少女算法,大家学了以后要记住这个算法的名字嗷。

代码:

struct Node{
int a,b,c;
}node[N];
int T,n,m,k;
int va[N];
int acc[N];
int ans,sum,suc = 1;
map<int,vector<PII> > mp;
int find(int x)
{
if(x!=acc[x]) acc[x] = find(acc[x]);
return acc[x];
}
void krukal()
{
for(int i=1;i<=n;i++) acc[i] = i;
for(auto t:mp)
{
int res = 0;
for(auto tt:t.se)
{
int t1 = find(tt.fi),t2 = find(tt.se);
if(t1!=t2) res++;
}
int res_t = 0;
for(auto tt:t.se)
{
int t1 = find(tt.fi),t2 = find(tt.se);
if(t1!=t2)
{
res_t++;
acc[t1] = t2;
ans += t.fi;
}
}
if(res>res_t) suc = 0; //如果还有边权可以用可以不用,那么就是不唯一的
}
}
signed main()
{
IOS;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
mp[c].pb({a,b});
}
krukal();
for(int i=1;i<=n;i++) if(find(i)==i) sum++;
if(sum==1)
{
cout<<ans<<"n";
if(suc) cout<<"Yesn";
else cout<<"Non";
}
else cout<<"No MSTn"<<sum<<"n";
return 0;
}
The Unique MST:
struct Node{
int a,b,c;
}node[N];
int T,n,m,k;
int va[N];
int acc[N];
int sum1,sum2,sum3;
int ans,cnt,suc;
bool cmp(Node A,Node B)
{
return A.c<B.c;
}
int find(int x)
{
if(x!=acc[x]) acc[x] = find(acc[x]);
return acc[x];
}
void krukal()
{
for(int i=1;i<=n;i++) acc[i] = i;
sort(node+1,node+1+m,cmp);
for(int i=1;i<=m;i++)
{
int idx = 0,res = 0,res_t = 0;
for(int j=i;j<=m;j++)
{
if(node[j].c==node[i].c) idx = j;
else break;
}
for(int j=i;j<=idx;j++)
{
int a = node[j].a,b = node[j].b;
int t1 = find(a),t2 = find(b);
if(t1!=t2)
{
res++;
sum1 += node[j].c;
}
}
for(int j=i;j<=idx;j++)
{
int a = node[j].a,b = node[j].b;
int t1 = find(a),t2 = find(b);
if(t1!=t2)
{
sum2 += node[j].c;
res_t++;
acc[t1] = t2;
ans += node[j].c;
}
}
if(res>res_t) suc = 0;
}
}
int main()
{
cin>>T;
while(T--)
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
node[i] = {a,b,c};
}
sum1 = sum2 = cnt = 0;
krukal();
for(int i=1;i<=n;i++) if(find(i)==i) cnt++;
if(cnt==1&&sum1==sum2) cout<<ans<<"n";
else cout<<"Not Unique!n";
}
return 0;
}

总结:
多多思考一些算法的本质。

最后

以上就是贪玩银耳汤为你收集整理的PTA-最小生成树的唯一性-(最小生成树的边权地位)的全部内容,希望文章能够帮你解决PTA-最小生成树的唯一性-(最小生成树的边权地位)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(34)

评论列表共有 0 条评论

立即
投稿
返回
顶部