[joint query set & & minimum spanning tree] how many tables, or smooth project

Time:2021-8-19

How many tables

Today is Ignatius’ birthday. He invites a lot of friends. Now it’s dinner time. Ignatius wants to know how many tables he needs at least. You have to notice that not all the friends know each other, and all the friends do not want to stay with strangers.

One important rule for this problem is that if I tell you A knows B, and B knows C, that means A, B, C know each other, so they can stay in one table.

For example: If I tell you A knows B, B knows C, and D knows E, so A, B, C can stay in one table, and D, E have to stay in the other one. So Ignatius needs 2 tables at least.
Input
The input starts with an integer T(1<=T<=25) which indicate the number of test cases. Then T test cases follow. Each test case starts with two integers N and M(1<=N,M<=1000). N indicates the number of friends, the friends are marked from 1 to N. Then M lines follow. Each line consists of two integers A and B(A!=B), that means friend A and friend B know each other. There will be a blank line between two cases.
Output
For each test case, just output how many tables Ignatius needs at least. Do NOT print any blanks.
Sample Input
2
5 3
1 2
2 3
4 5

5 1
2 5
Sample Output
2
4

//(concurrent search)
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<cstdio>
#include<queue>
#include<stack> 
#include<set> 
#include<vector> 
using namespace std;
const int maxn = 1005;
int s[maxn];// Join set array 
Int find (int x) {// find the set where a node is located 
    if(x == s[x]){
        return x;
    }else{
        s[x] = Find(s[x]);// Keep looking up Father recursively and compress the path 
        return s[x];
    }
}

Void unionn (int i, int j) {// merge the set of I, j 
    int i_f = Find(i);
    int j_f = Find(j);
        if(i_f != j_f){
            s[i_ f] = j_ f;// The ancestor of I (representing the element or set) is J
        } 
    }

int main(){
    int t = 0;
    cin >> t;
    while(t--){
        int n = 0,m = 0;
        cin >> n >> m;
        for(int i = 1; i <= maxn; i++){
            s[i] = i;// The initial set of each number is itself 
        }
        int x,y;// Enter two groups of friends you know 
        for(int j = 1; j <= m; j++){
            cin >> x >> y;
            unionn(x,y);// Merge the collection of two friends 
        }
        int ans;
        ans = 0;
        for(int k = 1; k <= n; k++){
            if(k == s[k]){
                ans++;
            }
        } 
        cout << ans << endl;
    }
    return 0;
}

[joint query set & & minimum spanning tree] how many tables, or smooth project

Or smooth engineering (minimum spanning tree)

The distance between any two villages is listed in the statistical table obtained by investigating the rural traffic situation in a province. The goal of the provincial government’s “unblocked project” is to enable highway traffic between any two villages in the province (but there is not necessarily a direct highway, as long as it can be reached indirectly through the highway), and the total length of the paved highway is required to be the minimum. Please calculate the minimum total highway length.
Input
The test input contains several test cases. The first line of each test case gives the number of villages n (< 100); The subsequent n (n-1) / 2 lines correspond to the distance between villages. Each line gives a pair of positive integers, which are the numbers of the two villages and the distance between the two villages. For simplicity, villages are numbered from 1 to n.
When n is 0, the input ends and the use case is not processed.
Output
For each test case, output the minimum total road length in 1 line.
Sample Input
3
1 2 1
1 3 2
2 3 4
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
0
Sample Output
3
5

Huge input, scanf is recommended.

In this paper, prime and Kruskal are used to solve the minimum spanning tree problem, and Kruskal is the main method

//Prime algorithm for minimum spanning tree
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<cstdio>
#include<queue>
#include<stack> 
#include<set> 
#include<vector> 
using namespace std;
const int INF = 0x3f3f3f3f;// The decimal system of x3f3f3f3f is 1061109567, and int_ Max is an order of magnitude, that is, the order of 10 ^ 9
//In general, the data are less than 10 ^ 9. 0x3f3f3f3f3f * 2 = 2122219134, the addition of infinity will not overflow. 
int m,n;// M represents the number of paths to be input in the map, and N represents the number of villages
int x,y,z;// x. Y and Z represent two villages and distance respectively
int dis[10005],vis[105];// Dis [] indicates the distance between two villages (DIS [i] indicates the length of all edges connected to point I), and vis [] indicates whether it has been selected as a crossing point 
int mp[100][100];// Assign an initial value to the distance between any two villages
void prime(){
    dis[1] = 0;// The starting point is 0, and only one point has no distance. Later, the for loop needs to be carried out point by point, and the first point also needs to be added to the set of existing points
    int k = 1;// Mark 1 as accessed first 
    while(1){
//        int k = 1;// Mark whether the shortest path from the existing point to other points has been found with the change of K, and assign that point to K
        int count = 0;         
        int minnum = INF;// The minnum value is changed back to inf each time the loop runs 
//        for(int j = 1; j <= n; j++){
//If (MP [k] [J] < dis [J] & & vis [J] = = 0) {// compare the distances of all points connected to K and find the shortest path from a point to other points 
//                dis[j] = mp[k][j];// Assign the smallest value to dis [J] 
//            }
//        }     
//        for(int i = 1;  i <= n;  I + +) {// find the smallest edge in the set of connected edges of existing points 
//If (DIS [i] < minnum & & vis [i] = = 0) {// if you find a dis [i] value smaller than the minnum value (find the point of the smallest edge connected to the points of the existing point set), replace the original minnum value 
//                minnum = dis[i];// The minnum value is changed back to inf each time the while loop 
//                k = i;// Indicates that a point K is found and added to the existing point set 
//            }
//        }
//If (k = = - 1) {// the K value has not changed, and the traversal has been completed. The VIS [] found in the above for() is not 0 
//            break; 
//        }
        vis[k] = 1;// Mark after adding to collection 
        for(int j = 1;  j <= n;  J + +) {// plays two roles: find the shortest path dis [1], [2], [3], [4].... connected to j at any point, and MP [1] [1], [2] [1], [3] [1], etc. constantly update the smallest dis [1] 
            If (MP [k] [J] < dis [J] & & vis [J] = = 0) {// compare the distances of all points connected to K and find the shortest path from a point to other points 
                dis[j] = mp[k][j];// Assign the smallest value to dis [J] 
            }
        }
        for(int i = 1;  i <= n;  I + +) {// find the smallest edge in the set of connected edges of existing points (the smallest value in each DIS) 
            If (DIS [i] < minnum & & vis [i] = = 0) {// if you find a dis [i] value smaller than the minnum value (find the point of the smallest edge connected to the points of the existing point set), replace the original minnum value 
                minnum = dis[i];// The minnum value is changed back to inf each time the while loop 
                k = i;// Indicates that a point K is found and added to the existing point set
                count++; 
            }
        }
        If (count = = 0) {// the count value has not changed, and the traversal has been completed. The VIS [] found in the above for() is not 0 
            break; 
        }     
    }
    int ans  = 0;
    for(int i = 1; i <= n; i++){
        ans += dis[i];// Add up all the shortest paths 
    }
    cout << ans << endl; 
} 

int main(){
    while(scanf("%d",&n)!=EOF,n != 0){
        m = n * (n - 1)/2;
        memset(vis,0,sizeof(vis));// Initialize tag array to 0 
        memset(dis,INF,sizeof(dis));// Initialize tag array to infinity
        for(int i = 1;  i <= n;  I + +) {// initialize MP adjacency matrix 
            for(int j = 1; j <= n; j++){
                If (I = = J) {// the distance from the point itself to itself is 0 
                    mp[i][j] = 0;
                }Else{// initialize other point-to-point distances to infinity 
                    mp[i][j] = mp[j][i] = INF; 
                } 
            }
        } 
        for(int i = 0; i < m; i++){
            cin >> x >> y >> z;// Assign values to points with paths between them, and the values between other unconnected points are still infinite 
            If (MP [x] [y] > z) {// prevent the occurrence of two groups of test data with the same village but different distance 
                mp[x][y] = z;// Make sure the distance is minimal 
                mp[y][x] = z;// Both sides of the adjacency matrix must be assigned values 
            }
        }
        prime(); 
    }
    return 0;
}

The following is the Kruskal algorithm combined with search set to find the minimum spanning tree

//(Kruskal algorithm (union search set) for minimum spanning tree) 
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<cstdio>
#include<queue>
#include<stack> 
#include<set> 
#include<vector> 
using namespace std;

//const int INF = 0x3f3f3f3f;// The decimal system of x3f3f3f3f is 1061109567, and int_ Max is an order of magnitude, that is, the order of 10 ^ 9
//In general, the data are less than 10 ^ 9. 0x3f3f3f3f3f * 2 = 2122219134, the addition of infinity will not overflow.
const int maxn = 105;
struct Edge{
    int u,v,w;// Village 1, village 2 and distance representing structural variables respectively 
}edge[maxn*maxn];// Define an adjacency table structure array 
bool cmp(Edge a,Edge b){
    return a.w < b.w;
} 
int m,n,s[maxn];// M represents the number of paths to be input in the map, n represents the number of villages, and s [maxn] represents the array set and is used for searching the set 
int Find(int x){
    if(x == s[x]){
        return x;
    }else{
        s[x] = Find(s[x]);// Keep looking up Father recursively and compress the path 
        return s[x];
    }
} 
int Kruskal(){
    int ans ;
    ans = 0;
    for(int i = 1;  i <= n;  I + +) {// initialization, and the set is its own 
        s[i] = i;
    }
    sort(edge,edge + m,cmp);
    for(int i = 0; i < m; i++){ 
        int b = Find(edge[i].u);
        int c = Find(edge[i].v);
        If (b = = C) {// indicates that the two vertices of edge [i] are already in the same set and do not need to be merged (tree ring can also be avoided here) 
            continue;
        }
        s[b] = c;
//        s[c] = b;
        ans += edge[i].w; 
    }
    return ans; 
} 

int main(){
    while(scanf("%d",&n)!=EOF,n){
        m = n * (n - 1)/2;
        for(int i = 0; i < m; i++){
            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
        }
        int ans;
        ans = 0; 
        ans = Kruskal();
        printf("%d\n",ans); 
    }
    return 0;
}

[joint query set & & minimum spanning tree] how many tables, or smooth project

Recommended Today

Java Engineer Interview Questions

The content covers: Java, mybatis, zookeeper, Dubbo, elasticsearch, memcached, redis, mysql, spring, spring boot, springcloud, rabbitmq, Kafka, Linux, etcMybatis interview questions1. What is mybatis?1. Mybatis is a semi ORM (object relational mapping) framework. It encapsulates JDBC internally. During development, you only need to pay attention to the SQL statement itself, and you don’t need to […]