Busy city (Bangchaji, Kruskal)

Description
City C is a very busy metropolis. The roads in the city are very crowded, so the mayor decided to renovate the roads. The roads of city C are distributed like this: there are n intersections in the city, some intersections are connected by roads, and at most one road is connected between two intersections. These roads are bidirectional and connect all intersections directly or indirectly. Each road has a score. The smaller the score, the busier the road and the more it needs to be modified. However, the city government’s funds are limited, and the mayor hopes that the fewer roads for renovation, the better, so he made the following request:

1. The reconstructed roads can directly or indirectly connect all intersections.

2. In the case of meeting Requirement 1, the number of roads to be reconstructed should be as few as possible.

3. In the case of meeting requirements 1 and 2, the score of the road with the highest score among the roads to be reconstructed should be as small as possible.

Task: As the city planning bureau, you should make the best decision to choose which roads should be built.
The
first line of Input has two integers n, m means that the city has n intersections and m roads.

The next m line is a description of each road, u, v, c indicate that there is a road connection between the intersection u and v, and the score is c.
Output
two integers, s,max, indicating how many roads you have selected, and what is the score of the road with the highest score.
Sample Input 1
4 5
1 2 3
1 4 5
2 4 7
2 3 6
3 4 8
Sample Output 1
3 6
Hint
(1≤n≤300, 1≤c≤10000, 1≤m≤100000)

Analysis: A look at the topics "Connect all intersections", "Renovate roads as few as possible", and "Renovate roads with the highest scores as small as possible", we can see that this meets the definition of minimum spanning tree. This problem is The bare minimum spanning tree problem.

AC code:

#include <stdio.h>
#include <algorithm>
#include <string.h>

struct EDGE//存边
{
    
    
    int u;//端点1
    int v;//端点2
    int val;//边权
    friend bool operator<(EDGE &edge1,EDGE &edge2)//排序规则
    {
    
    
        return edge1.val<edge2.val;
    }
}edge[100010];

int n,m;//点数,边数
int ans;//记录最小生成树的最大边边权
int cnt=0;//记录当前已选多少条边
int parent[310];//记录父节点
int rank[310];//记录树层数,只有一个节点算0层

inline void initialise()//初始化
{
    
    
    for(int i=1;i<=n;++i)
    {
    
    
        parent[i]=i;//开始时每个端点都是独立的,自己是自己父节点
    }
    memset(rank,0,sizeof(rank));//开始时都是0层
}

int find_root(int x)//寻找根节点
{
    
    
    int x_root=x;
    while(parent[x_root]!=x_root)
    {
    
    
        x_root=parent[x_root];
    }
    return x_root;
}

int union_vertices(int x,int y)//合并两个节点到一个集合
{
    
    
    int x_root=find_root(x);
    int y_root=find_root(y);

    if(x_root==y_root){
    
    //合并将产生环,不能合并
        return 0;
    }
    else {
    
    
    	//合并时进行路径压缩,层数小的树合并到层数大的树上不增加其层数
    	//两棵层数相等的树合并,层数增1
        if(rank[x_root]>rank[y_root])
        {
    
    
            parent[y_root]=x_root;
        }
        else if(rank[x_root]<rank[y_root])
        {
    
    
            parent[x_root]=y_root;
        }
        else {
    
    
            parent[x_root]=y_root;
            ++rank[y_root];
        }
        return 1;
    }
}

int main()
{
    
    
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;++i)
    {
    
    
        scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].val);
    }
    std::sort(edge,edge+m);//给边排序
    initialise();
    for(int i=0;i<m;++i)//从最小边开始挑选,成环则不选
    {
    
    
        if(union_vertices(edge[i].u,edge[i].v))
        {
    
    
            ++cnt;
            ans=edge[i].val;
            if(cnt==n-1) break;
        }
    }
    printf("%d %d",n-1,ans);//打印答案
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_44643644/article/details/108567060