Violet_Evergardon @ 2024-08-12 11:47:11
我是直接存边,用两条有向边表示一条无向边
#include<iostream>
#include<stdio.h>
#include<queue>
using namespace std;
const int N=5005;
const int M=2e5+5;
int n,m,cnt,ans;
int fa[N];
struct B{
int u,v,w;
}edge[M];
struct cmp{
bool operator()(B a,B b){return a.w>b.w;}
};
priority_queue<B,vector<B>,cmp> q;
int find(int a){
if(fa[a]!=a) return fa[a]=find(fa[a]);
return fa[a];
}
void jianbian(int a,int b,int c){
edge[++cnt].u=a,edge[cnt].v=b,edge[cnt].w=c;
q.push(edge[cnt]);
}
void mix(int a,int b)
{
if(fa[a]==fa[b]) return ;
fa[a]=find(a),fa[b]=find(b);
fa[fa[b]]=fa[a];
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
jianbian(a,b,c);jianbian(b,a,c);
}
//Kruskal
for(int i=1;i<=n-1;i++)
{
B t=q.top();
while(find(t.u)==find(t.v)) q.pop(),t=q.top();
ans+=t.w;
mix(t.v,t.u);
}
for(int i=2;i<=n;i++)
if(find(1)!=find(i))
{
cout<<"orz"<<endl;
return 0;
}
cout<<ans<<endl;
return 0;
}
by Fur_Zes @ 2024-08-12 11:51:38
@Violet_Evergardon 为什么要用有向边啊/yiw
by Fur_Zes @ 2024-08-12 11:52:49
@Violet_Evergardon 用并查集直接去看当前节点是否在生成树里就好了啊,你这建了双倍的边浪费空间的
by _8008008 @ 2024-08-12 11:55:45
@As2O3 应该不是这里的问题,用两个有向边表示无向边是常规操作
by Fur_Zes @ 2024-08-12 11:57:36
@_8008008 但是他浪费空间啊,lz有报错MLE的
by _8008008 @ 2024-08-12 11:59:05
那试试吧
by Violet_Evergardon @ 2024-08-12 16:37:55
@As2O3 是这个问题,在这里确实没有必要建两边。改过后就没有MLE了。但#13还是T了,是因为用堆了吗?虽然一个sort可以搞定,但都是nlogn的复杂度啊。
by Fur_Zes @ 2024-08-12 16:41:37
@Violet_Evergardon 可能是,但我没学堆排,我尽量帮忙找找问题
by Fur_Zes @ 2024-08-12 17:01:18
@Violet_Evergardon
while(find(t.u)==find(t.v)) q.pop(),t=q.top();
这句话太慢了,个人感觉这个for套while可以卡到