0
点赞
收藏
分享

微信扫一扫

图论刷题计划与题解2(最小生成树)

Yaphets_巍 2022-02-01 阅读 77

文章目录

最小生成树

题目1: P3366 【模板】最小生成树

prim 求最小生成树O(n^2) 朴素版

#include<bits/stdc++.h>
using namespace std;
const int N = 5010;

const int INF = 0x3f3f3f3f;
int n ,m;
int g[N][N];
int dist[N];
bool st[N];
int prim()
{
    memset(dist,0x3f,sizeof dist);
    dist[1] = 0;
    int res = 0;
    for(int i = 0;i<n;i++)
    {
        int t = -1;
        for(int j = 1;j<=n;j++)
        {
            if(!st[j]&&(t==-1||dist[t]>dist[j]))
                t = j;
        }
        if(i&&dist[t]==INF) return INF;
        if(i) res+=dist[t];
        st[t] = true;
        for(int j = 1;j<=n;j++) dist[j] = min(dist[j],g[t][j]);   
    }
    return res;
}
int main()
{
    memset(g,0x3f3f3f3f,sizeof g);
    cin>>n>>m;
    while(m--)
    {
        int a,b,c;
        cin>>a>>b>>c;
        g[a][b] = g[b][a] = min(g[a][b],c);
    }
    int t = prim();
    if(t==INF) puts("orz");
    else cout<<t;
    return 0;
}

kruskal求最小生成树 O(mlogm)

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

int n,m;
const int N = 1e5+10;
int p[N];
int find(int x)
{
    if(p[x]!=x) p[x] = find(p[x]);
    return p[x];
}
struct Edge{
    int a,b,w;
    bool operator<(const Edge &W) const
    {
        return w<W.w;
    }
}edges[2*N];
int main()
{
    cin>>n>>m;
    for(int i = 0;i<m;i++)
    {
        int a,b,w;
        cin>>a>>b>>w;
        edges[i] = {a,b,w};
    }
    sort(edges,edges+m);
    
    for(int i = 1;i<=n;i++) p[i] = i;
    
    int res = 0,cnt = 0;
    for(int i= 0;i<m;i++)
    {
        int a = edges[i].a, b= edges[i].b,w = edges[i].w;
        a = find(a),b = find(b);
        if(a!=b)
        {
            p[a] = b;
            res+=w;
            cnt++;
        }
    }
    if(cnt<n-1) puts("orz");
    else cout<<res;
    return 0;
}

题目2: P1546 [USACO3.1]最短网络 Agri-Net

#include<bits/stdc++.h>
using namespace std;
const int N = 210;

const int INF = 0x3f3f3f3f;
int n,m;
int g[N][N];
int dist[N];
bool st[N];

//O(n^2)
int prim()
{
    memset(dist,0x3f,sizeof dist);
    //先初始化dist数组
    int res = 0;
    dist[1] = 0;
    for(int i = 0;i<n;i++)
    {
        int t = -1;
        for(int j = 1;j<=n;j++)
        {
            if(!st[j]&&(t==-1||dist[t]>dist[j]))
            {
                t = j;
            }
        }
        res+=dist[t];//如果i==0说明只有一个点,不可能有边
        st[t] = true;
        for(int j = 1;j<=n;j++)
            dist[j] = min(dist[j],g[t][j]);
    }
    return res; 
}
int main()
{
    memset(g,0x3f3f3f3f,sizeof g);
    cin>>n;
    for(int i = 1;i<=n;i++)
    {
        for(int j = 1;j<=n;j++)
            cin>>g[i][j];
    }
    int t = prim();
    cout<<t;
    return 0;
}

题目3:P2820 局域网

kruskal模板题

/*
1.将所有边按权重从小到大排序 O(mlogm)
2.枚举每一条边a->b 权重为c
    if(!st[a][b]) 将a,b加入集合中

*/
#include<iostream>
#include<algorithm>

using namespace std;
const int N = 100010;

int n,m;
int p[N];

struct Edge
{
    int a,b,w;
    
    bool operator<(const Edge &W) const
    {
        return w<W.w;
    }
}edges[2*N];

int find(int x)
{
    if(p[x]!=x) p[x] = find(p[x]);
    return p[x];
}
int main()
{
    cin>>n>>m;
    int sum = 0;
    for(int i = 0;i<m;i++)
    {
        int a,b,w;
        cin>>a>>b>>w;     
        sum+=w;
        edges[i] = {a,b,w};
    }
    sort(edges,edges+m);
    
    for(int i = 1;i<=n;i++) p[i] = i;
    
    int res = 0,cnt = 0;
    for(int i= 0;i<m;i++)
    {
        int a = edges[i].a, b= edges[i].b,w = edges[i].w;
        a = find(a),b = find(b);
        if(a!=b)
        {
            p[a] = b;
            res+=w;
            cnt++;
        }
    }
    cout<<sum-res;
    return 0;
}

题目4:P2330 [SCOI2005]繁忙的都市

挺有意思的一个题,需要注意先把编号p为1的数据预处理了过后,再去处理p=2的数据,不然可能会多计数…kruskal解决~

#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N = 310,M = 8010;
struct edge{
    int a,b,w;
    bool operator< (const edge &W)const{
        return w<W.w;
    }
}edges[M];
int p[N];
int find(int x)
{
    if(x!=p[x]) return p[x] = find(p[x]);
    return x;
}
int main()
{
    cin>>n>>m;
    for(int i = 0;i<m;i++)
    {
        cin>>edges[i].a>>edges[i].b>>edges[i].w;
    }
    sort(edges,edges+m);
    for(int i = 1;i<=n;i++)
        p[i] = i;
    int res = 0,cnt = 0;
    for(int i = 0;i<m;i++)
    {
        int a = edges[i].a,b = edges[i].b,w = edges[i].w;
        int pa = find(a),pb = find(b);
        if(pa!=pb)
        {
            p[pa] = pb;
            res = max(res,w);
            cnt++;
        }
    }
    cout<<cnt<<" "<<res;
}
举报

相关推荐

0 条评论