Programming Thinking Week6 Assignment C- Mastering Magic No Toto I

topic

Dongdong is bored in his hometown and wants to farm. There are n blocks of farmland, numbered from 1 to n. Farming
is a must. It is well known that Dongdong is a magician. He can consume a certain amount of MP to cast magic on a field, making the water of the Yellow River come to the sky. He can also consume a certain amount of MP to build a portal on the canals of two fields, so that this field refers to the water of the field with water (1 <= n <= 3e2).
The consumption from the sky of the Yellow River is Wi, and i is the farmland number (1 <= Wi <= 1e5).
The cost of building a portal is Pij, and i and j are farmland numbers (1 <= Pij <= 1e5, Pij = Pji, Pii = 0).
Dongdong is the minimum consumption of all the fields.

Input

Line 1: a number n,
line 2 to line n + 1: line wi,
line n + 2 to line 2n + 1: matrix is ​​the pij matrix

Output

Dong Dong's minimum MP value

Sample Input

4
5	
4
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0

Sample Output

9	

Ideas

The problem can be viewed as an undirected weighted graph based only on the establishment of a portal, with a weight value of the MP that establishes the portal between the two farmlands. In order to deal with the sky of the Yellow River, another piece of farmland 0 can be added to connect the farmland to every other farmland, and the weight of the side is the MP of the sky of the yellow river.
In this way, the problem becomes the problem of finding the minimum spanning tree for undirected weighted graphs. You can use prim or kruskal to find the minimum spanning tree.

  • prim: A point-based greedy algorithm. The core idea is to maintain a connected point set. From each point that is not in the point set, a point with the least cost to connect the point set is selected and added to the point set.
  • kruskal: every time you greedily try to mark the smallest non-tree edge in the graph as a tree edge, and illegally skip it.

This question uses kruskal. Use and check whether the two points are connected.
All the edges are sorted according to the weight value from small to large;
consider each edge in order (the order of the edge weights from small to large), as long as this edge does not form a circle with the edge we have selected, keep this edge, otherwise Abandon this edge; after
successfully selecting (n-1) edges, form a minimum spanning tree. Of course, if the algorithm cannot select (n-1) edges, it means that the original graph is not connected.

Code

#include <cstdio>
#include <algorithm>
using namespace std;
int n,edges=0;
int field[305][305];
int father[300];
struct edge{
    int u,v,w;
    bool operator<(edge e)const{
        return w<e.w;
    }
}e[300*300+5];

int find(int x){
    if(father[x]==x)
        return x;
    return father[x]=find(father[x]);
}

bool unit(int x,int y){
    x=find(x);y=find(y);
    if(x==y)
        return false;
    father[y]=x;
    return true;
}

int kruskal(){
    sort(e,e+edges);
    int ans=0,cnt=0;
    for(int i=0;i<edges;i++){
        if(unit(e[i].u, e[i].v)){
            ans+=e[i].w;
            cnt++;
            if(cnt==n)
                break;
        }
    }
    return ans;
}

int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&field[0][i]);
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&field[i][j]);
    for(int i=0;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            e[edges].u=i;
            e[edges].v=j;
            e[edges].w=field[i][j];
            edges++;
        }
    }
    for(int i=0;i<=n;i++)
        father[i]=i;
    int ans=kruskal();
    printf("%d",ans);
    return 0;
}

Title link

Published 24 original articles · praised 2 · visits 435

Guess you like

Origin blog.csdn.net/weixin_43805228/article/details/105184535