Kruskal除了最后一个ac其他全wa,read o

P3366 【模板】最小生成树

Taoran123 @ 2024-03-26 22:07:41

#include<iostream>
#include<algorithm> //sort()所在头文件 
using namespace std;
int n,m;//n为节点数,m为边数
int ans=0; 
int father[5001] ;//记录每个点所在树的父结点      (kruskal在不断合并树) 
int f[5001][5001]; 
struct Edge
{
    int u,v;
    int weight; //边权 
}edge[200001];
bool cmp(Edge a,Edge b)//结构体的sort规则
{
    return a.weight<b.weight;//按edge.weight值 从小到大排序 
 } 
int findf(int x) //并查集  找祖宗并返回(1.压缩路径 2.途经点的父亲都改为了祖宗点) 
{
    if(father[x]==x)
    {
        return x;
    }
    else {
        father[x]=findf(father[x]);//找祖宗 
    }
}
void Kruskal()//kruskal时间复杂度eloge 
{
    //步骤1   排序边权,初始化 
    int tot=0;
    sort(edge+1,edge+m+1,cmp) ;//排序       (从结构体数组edge的序号1到序号m)
    for(int i=1;i<=n;i++) father[i]=i;//初始化父节点也就是并查集 
    //步骤2   从小到大添加边,利用并查集合并不同的树(也就避免了产生回路) 
    for(int i=1;i<=m;i++) //从小到大遍历边 
    {
        int uf,vf;
        uf=findf(edge[i].u) ;vf=findf(edge[i].v) ;
        if(uf!=vf)//如果不在同一个树,合并两棵树     (也就是加上这个边) 
        {
            tot++;
            ans+=edge[i].weight;
            father[edge[i].u] =edge[i].v;//让u的父亲是v,这样下次findf时候会①自动把u的父亲改为v的父亲,②其他点经过u时候也会把父亲改为v的父亲 
        }
        if(tot==n-1) 
        {
            cout<<ans; 
            break; 
        }
    }
    if(tot!=n-1)
    {
        cout<<"orz";
    }
}

int main(){
    //读入 
    cin>>n>>m;//读入节点数、边数 
    for(int i=1;i<=m;i++)//将边的信息读入 
    {
        int u,v,w;//节点u到节点m的边 权值为w 
        if(u!=v)//去掉自环 
        {
            cin>>u>>v>>w; 
        }
        if(f[u][v]==0)//去掉重边 
        {
            edge[i].u=u;
            edge[i].v=v;
            edge[i].weight=w;
            f[u][v]=w;
            f[v][u]=w;
        }
        else if(f[u][v]>w){
            edge[i].u=u;
            edge[i].v=v;
            edge[i].weight=w;
            f[u][v]=w;
            f[v][u]=w;
        }

        /*cin>>u>>v>>w;
        edge[i]={u,v,w};//把边信息存入结构体edge[i] 
        */
    }
    Kruskal();//使用kruskal算法进行稀疏图的最小生成树生成。

    return 0; 
} 

}

int main(){ //读入 cin>>n>>m;//读入节点数、边数 for(int i=1;i<=m;i++)//将边的信息读入 { int u,v,w;//节点u到节点m的边 权值为w if(u!=v)//去掉自环 { cin>>u>>v>>w; } if(f[u][v]==0)//去掉重边 { edge[i].u=u; edge[i].v=v; edge[i].weight=w; f[u][v]=w; f[v][u]=w; } else if(f[u][v]>w){ edge[i].u=u; edge[i].v=v; edge[i].weight=w; f[u][v]=w; f[v][u]=w; }

    /*cin>>u>>v>>w;
    edge[i]={u,v,w};//把边信息存入结构体edge[i] 
    */
}
Kruskal();//使用kruskal算法进行稀疏图的最小生成树生成。
return 0; 

}


by __ryp__ @ 2024-03-26 22:32:33

@Taoran123 并查集 else 分支没 return


by __ryp__ @ 2024-03-26 22:33:29

@Taoran123 另外这题不需要判重边


by Taoran123 @ 2024-03-26 22:55:08

@intirain 改了一下变成后3个ac,前面的全都是输出o


|