[Graph Theory-Minimum Spanning Tree] Summary of Luogu Official Question List

#Minimum spanning tree

Undirected graph G=(V,E) n个顶点,m条边 Use the edges in the graph to connect all vertices (n vertices, you need n-1 edges) This subgraph is called a spanning tree , and the subgraph with the smallest sum of the weights of the edges used is called is the minimum spanning tree.

kruskal's algorithm (adding edges)

step1 . Sort all edges by weight (two endpoints or two connected components in the spanning tree must be connected by the edge that exists and has the smallest weight)

insert image description here **step2** All points as a separate set (a point is a set) (union set initialization) **step3** will connect the sets through edges, and the final spanning tree is that all points are in a set. Select to add a new edge (sorted is optimal), if the two endpoints connected by the edge are no longer in the same set (and check the set), add the edge, and merge the two sets (and check the set merge) ).

Luogu - Minimum Spanning Tree Template

P1546 [USACO3.1] Shortest Network Agri-Net

Given the graph as an adjacency matrix, solve for the minimum spanning tree cost. Both kruskal and prime algorithms are fine.

#include<bits/stdc++.h>
using namespace std;
#define Maxx 10010
int N,ans,cnt,val,x,y;
int p[Maxx];
struct Node{
    
    
    int x,y,val;
}a[Maxx];
bool cmp(Node n1,Node n2){
    
    
    return n1.val<n2.val;
}
void init(){
    
    //初始化
    for(int i=1;i<Maxx;i++) p[i]=i;
}
int getP(int x){
    
    //获取父亲
    if(p[x]!=x) return p[x]=getP(p[x]);//压缩路径压缩
    return x;
}
int kruskal(){
    
    
    sort(a+1,a+cnt+1,cmp);
    init();
    for(int i=1;i<=cnt;i++){
    
    //遍历边
        x=a[i].x;
        y=a[i].y;
        int px=getP(x),py=getP(y);
        if(px!=py){
    
    //边的两个顶点不再同一个集合则加入,并且合并两集合
            p[py]=px;//合并操作
            ans+=a[i].val;//累加生成树边权值
        }
    }
}
int main()
{
    
    
    cin>>N;
    for(int i=1;i<=N;i++){
    
    
        for(int j=1;j<=N;j++){
    
    
            cin>>val;
            if(val!=0) a[++cnt]={
    
    i,j,val};
        }
    }
    kruskal();
    cout<<ans<<endl;
}

Luogu_USACO_Building_Roads_S minimum cost of connection

Problem Description
At a point in the coordinate system n 坐标(,x,y), give man edge 连接(i,j)whose length is equal to the distance in the coordinate system. Ask to add the minimum length of the edge so that all points are connected.
The idea of ​​the topic The
minimum spanning tree has the property of being connected and costing the least weight. For the edges that have been added (m existing edges), the cost is 0, and then enumerate any two points to obtain a complete graph, and then use kruskalthe cost of calculating the minimum spanning tree.
Code

#include<bits/stdc++.h>
using namespace std;
#define N 500010
struct Node{
    
    
    int x,y;
    double val;
};
Node a[N],b[N];
int n,m,x,y,w,cnt;
double sum;
int p[5100];
bool cmp(Node n1,Node n2){
    
    
    return n1.val<n2.val;
}
void init(){
    
    
    for(int i=1;i<=n;i++) p[i]=i;
}
int findP(int x){
    
    
    if(p[x]==x) return x;
    return p[x]=findP(p[x]);
}
void kruskal(){
    
    
    for(int i=1;i<=cnt;i++){
    
    
        int px=findP(a[i].x);
        int py=findP(a[i].y);
        if(px!=py){
    
    
            p[px]=py;
            sum+=a[i].val;
        }
    }
}
int main()
{
    
     
    cin>>n>>m;
    for(int i=1;i<=n;i++){
    
    
        cin>>b[i].x>>b[i].y;
    }
    init();
    for(int i=1;i<=m;i++){
    
    
        cin>>x>>y;
        int px=findP(x),py=findP(y);
        p[px]=py;
    }
    for(int i=1;i<=n;i++){
    
    
        for(int j=i+1;j<=n;j++){
    
    
            a[++cnt].x=i;
            a[cnt].y=j;
            double dx=1.0*(b[i].x-b[j].x);
            double dy=1.0*(b[i].y-b[j].y);
            a[cnt].val=sqrt(dx*dx+dy*dy);
        }
    }
    sort(a+1,a+1+cnt,cmp);
    kruskal();
    printf("%.2f",sum);
}

prim algorithm (add point method)

primAlgorithms are similar to dijkstraalgorithms,

Step1. Add node 1 to spanning tree set T, and the rest are spanning tree set S. D[i]Mark the minimum distance from any point of set S to i in set T with an array, and vis[x]mark whether vertex x is in spanning tree set S. (initial D[i]=G[1,i] vis[1]=1 vis[其余]=0)

Step 2. Every D[i]time the vertex that finds the minimum value and is not in the set S i, update D[j] iand connect jwith edges ( D[j]=min(D[i],G[i][j])) until all vertices are added to the spanning tree set S.

Heap-optimized prim algorithm to implement template questions

#include<bits/stdc++.h>
using namespace std;
#define NUM 5100
int n,m,k,x,y,z,ans,cnt;
int vis[NUM],d[NUM];
//prim算法数据结构,vis数组(是否加入生成树集合) d数组距离(选择最优)
priority_queue< pair<int,int> >q;
//大根堆,使用负数变为小根堆,第一维为-d[i],第二位i
int head[NUM],next_[400005],ver[400005],edge[400005],tot;//数组模拟邻接表
//注意点!!! M≤2×10^5 因为是双向边存储所以边的数目必须是这个数据的二倍 
void add(int x,int y ,int z){
    
    
    ver[++tot]=y;
    edge[tot]=z;
    next_[tot]=head[x];
    head[x]=tot;
}
void prim(){
    
    
    //如果多组数据不要忘了初始化,memset可能会超时可以选择循环赋值
    memset(d,0x3f,sizeof(d));
    d[1]=0;
    q.push(make_pair(0,1));
    while(!q.empty()&&cnt<n){
    
    
        x=q.top().second;z=-q.top().first;
        q.pop();
        if(vis[x]) continue;
        cnt++;
        ans+=d[x];
        vis[x]=1;
        for(int i=head[x];i;i=next_[i]){
    
    
            y=ver[i],z=edge[i];
            if(!vis[y]&&d[y]>z){
    
    
                d[y]=z;
                q.push(make_pair(-d[y],y));
            }
        }
    }
}
int main()
{
    
    

    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
    
    
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);//无向边加上相反边
    }
    prim();
    if(cnt==n) cout<<ans;
    else cout<<"orz";
}

Luogu_P1991_Wireless Communication Network

Title description
There are n outposts in the coordinate system. Communication between outposts requires communication equipment. There are two types of communication devices available.
1. Both outposts are equipped with satellite communication, which can realize 0-distance cost communication.
2. Install wired equipment, which can only communicate at a maximum distance of D. Because device standards need to be unified, the maximum communication distance of all wired devices is the same.
Now to enable all outposts to communicate directly or indirectly in some way, given the number of devices that can be installed with satellite communication, if the number is insufficient, you need to install wired devices. What is the communication distance D of the wired devices?
Problem-solving ideas
Make all outposts connected , spanning tree? According to the title, considering related factors, satellite communication does not occupy and does not require any wired cost, so s satellite devices can connect s outposts without cost. The remaining n-s(set post set A) and s(set post set B) need to be connected through wired equipment , and at the same time need to be connected by Aline . Calculate the maximum cost, and that's the answer.AB

#include<bits/stdc++.h>
using namespace std;
#define N 510
int s,n,v[N],x,y,w;
double d[N],g[N][N],cost[N];//cost加入点i的花销
pair<int,int>a[N];//保存个哨所坐标
priority_queue<pair<int,int> >heap;
void prim(){
    
    //只需加入n-s+1个点,不如将加入的n-1个点的权值放在数组中,排序取后n-s个小的
    for(int i=1;i<=n;i++) d[i]=100100;//不要忘记初始化哦
    d[1]=0;
    heap.push(make_pair(0,1));
    while(!heap.empty()){
    
    
        x=heap.top().second;
        heap.pop();
        if(v[x]) continue;
        v[x]=1;
        cost[x]=d[x];
        //cout<<x<<':'<<endl;
        for(int i=1;i<=n;i++){
    
    
            //printf("d[%d]=%f g[%d][%d]=%f\n",i,d[i],x,i,g[x][i]);
            if(!v[i]&&d[i]>g[x][i]){
    
    
                d[i]=g[x][i];
                heap.push(make_pair(-d[i],i));
            }
        }
    }
    //for(int i=1;i<=n;i++) cout<<cost[i]<<' ';
    //cout<<endl;
    sort(cost+1,cost+1+n);//n-(s-1)=n-s+1
    printf("%.2f",cost[n-s+1]);
}
int main()
{
    
    
    cin>>s>>n;
    for(int i=1;i<=n;i++) cin>>a[i].first>>a[i].second;
    if(s>=n){
    
    
        cout<<0<<endl;
        return 0;
    }
    for(int i=1;i<=n;i++) g[i][i]=0;
    for(int i=1;i<=n;i++){
    
    
        for(int j=i+1;j<=n;j++){
    
    
            double dx=a[i].first-a[j].first;
            double dy=a[i].second-a[j].second;
            g[j][i]=g[i][j]=sqrt(dx*dx+dy*dy);
        }
    }
    prim();
}

It's over, we can only go here (time: 2022/3/22 5:25, indeed *25 can't be reached). Maybe the ability is limited, maybe the effort is not enough.
The plan has not been completed, and it has no meaning in the short term.
It seems to be caught in a loop, so far away, so far away.
Give yourself a buffer, after 4.15, see you later, will be back.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324372322&siteId=291194637