Week6 assignment

A Question Krypton Gold Belt East

Title description

There was a computer (number 1) in the laboratory. Recently, Kryptonian Kurudong purchased N-1 computers for the laboratory, numbered 2 to N. Each computer is connected to a previously installed computer with a network cable. But Gugudong is worried that the network speed is too slow, he wants to know the maximum cable length from the i-th computer to other computers, but poor Gugudong has just suffered a de-smart attack from cosmic rays not long ago. Please help him.
Insert picture description here
Tip: The sample input corresponds to this figure. From this figure, you can see that the computer farthest from computer 1 is computer 4, and the distance between them is 3. Computer No. 4 and Computer No. 5 are the farthest points from Computer No. 2, so the answer is 2. Computer No. 5 is the farthest away from Computer No. 3, so for Computer No. 3, its answer is 3. In the same way, we can calculate that the answer for computer 4 and computer 5 is 4.
input: The
input file contains multiple sets of test data. For each set of test data, the first line is an integer N (N <= 10000), then there are N-1 lines, two numbers in each line, and for the two numbers in the i-th line, they represent the number connected to computer i The computer number and the length of the network cable between them. The total length of the network cable will not exceed 10 ^ 9, and each number is separated by a space.
output:
For each set of test data, output N lines, the i-th line represents the answer of the computer i (1 <= i <= N).

Sample Input
5
1 1
2 1
3 1
1 1
Sample Output
3
2
3
4
4
Ideas

The longest distance from each point required here to other points, the longest distance here can only be the farthest distance from the diameter, the problem is how to find the diameter point, here first use dfs to find the distance of any point Far point v1, and then dfs again to find the farthest point v2 of v1. In the process of calculating v2, we have obtained the coordinates of v1 to each point. Here we also need to use dfs to get the distance of v2 to each point. Finally Just output the larger value

Code
#include<iostream>
#include<stdio.h>
#include<vector>
#include<string.h>
#define MAx 10000
using namespace std;
struct edge
{
    int d,w;
   edge(int i,int j):d(i),w(j){};
};
vector<edge> p[MAx+1];
int t1,t2,v1,v2,n,mdis,dis[MAx+1],dis1[MAx+1];

bool vis[MAx+1];
void dfs(int s)
{
    vis[s]=1;  
    for(int i=0;i<p[s].size();i++)
    {
        if(!vis[p[s].at(i).d])
        {
            dis[p[s].at(i).d]=dis[s]+p[s].at(i).w;
            dfs(p[s].at(i).d);
        }
    } 
}
void dfss(int s)
{
    vis[s]=1;  
    for(int i=0;i<p[s].size();i++)
    {
        if(!vis[p[s].at(i).d])
        {
            dis1[p[s].at(i).d]=dis1[s]+p[s].at(i).w;
            dfss(p[s].at(i).d);
        }
    } 
}
int find()
{
    int ma=dis[1],t=1;
    for(int i=2;i<=n;i++)
    
        if(dis[i]>ma)
            ma=dis[i],t=i;
    return t;
}
int main()
{
    while ( scanf("%d",&n)!=EOF)
    {
        for(int i=2;i<=n;i++)
        {
            scanf("%d%d",&t1,&t2); 
            p[i].push_back({t1,t2});
            p[t1].push_back({i,t2});
        }
        memset(vis,0,sizeof(vis));
        dis[1]=0;
        dfs(1);
        v1=find();
        memset(vis,0,sizeof(vis));
        dis[v1]=0;
        dfs(v1);
        v2=find();
        dis1[v2]=0;
        memset(vis,0,sizeof(vis));
        dfss(v2);
        for(int i=1;i<=n;i++)
        printf("%d\n",dis[i]>dis1[i]?dis[i]:dis1[i]);
        for(int i=1;i<=n;i++)p[i].clear();
    }
    // system("pause");
    return 0;
}
 
to sum up

Although this question is A, but I still do n’t understand this diameter, I still need to learn it.

Take a good mask for question B!

Title description

The new corona virus pneumonia (Corona Virus Disease 2019, COVID-19), referred to as "new coronary pneumonia", refers to pneumonia caused by 2019 new coronavirus infection.
If an infected person enters a group, then this group needs to be isolated!
Little A student was diagnosed with a new crown infection and did not wear a mask! Quickly find all the students who have been in direct or indirect contact with Xiao A and isolate them to prevent a wider spread. As we all know, student communication may be divided into small groups, and a student may participate in multiple small groups at the same time.
Please write a program to solve it! wear mask! !
Input
multiple sets of data, for each set of test data: the
first line is two integers n and m (n = m = 0 indicates the end of input, no need to process), n is the number of students, m is the number of student groups. 0 <n <= 3e4, 0 <= m <= 5e2
student number is 0 ~ n-1A number is 0.
Then, m rows, each row has an integer num that is the number of small group personnel. Then there are num integers representing the students of this small group.
Output
outputs the number of people to be isolated, and the answer output of each group of data occupies one line

Ideas

This is a typical merging problem, stating that the two arrays represent the element category and quantity, respectively. The initial pre arrays are all themselves, and the sz arrays are all 1.
The merge operation merges, when the two students are not a group before, the group representative of i is added to the group of j, and the size of j is updated. To merge, just output the number of groups where 0 is located.

Code
#include<stdio.h>
#include<string.h>
using namespace std;
int pre[30002],m,n,sz[30002];
int find(int i)
{
    return i==pre[i]?i:find(pre[i]);
}
bool merge(int i,int j)
{
    i=find(i);
    j=find(j);
    if(i==j)return 0;
    pre[i]=j;
    sz[j]+=sz[i];
    return 1;
}
int main()
{
    cin>>n>>m;
    while(!(n==0&&m==0))
    {
        for(int i=0;i<n;i++)
        {
            pre[i]=i;
            sz[i]=1;
        }        
        for(int i=0;i<m;i++)
        {
            int t,t1,t2=-1;
            cin>>t;
            for(int j=0;j<t;j++)
            {
                cin>>t1;
               // cout<<t1<<"  ";
                if(t2!=-1)
                    merge(t1,t2);
                else
                    t2=t1;
            } 
        }
        cout<<sz[find(0)]<<endl;
        cin>>n>>m;
    }
   // system("pause");
    return 0;
}

to sum up

The simple way of writing the parallel check of this question is good. Fortunately, this question is very special. You only need to add the number entered later to the group of the number entered first to get a good combination. The form of the check is that the height is not Very high.

C question magic stuff

Title description

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 references the water of the field with water. (1 <= n <= 3e2)
The water consumption in the sky of the Yellow River is Wi, i is the farmland number (1 <= Wi <= 1e5)
. The consumption for establishing the portal is Pij, and i and j are the farmland numbers (1 <= Pij <= 1e5, Pij = Pji, Pii = 0)
Dongdong is the minimum consumption of all fields irrigation
input
Line 1: a number n
line 2 to line n + 1: number wi
line n + 2 to Line 2n + 1: The matrix is ​​the pij matrix
Output
MP value of the least consumed MP

样例

Input  
4
5
4
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0  
Output  
9
Ideas

This question treats sky as a super origin and can be solved as a minimum spanning tree problem. The combination check in question B is used to assist in the judgment. The edges are sorted and selected once, until the selection is complete or enough. n-1 stops.

Code
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;

struct edge
{
    int s,d,w;
    bool operator <(const edge&e)const{
        return w<e.w;
    }
};
int pre[305] ;
int find(int i)
{
    return i==pre[i]?i:find(pre[i]);
}
bool merge(int i,int j)
{
    i=find(i);
    j=find(j);
    if(i==j)return 0;
    pre[i]=j; 
    return 1;
}
edge e[50000];
int n,w,cnt,c,ans;
int main()
{
    scanf("%d",&n);
    for(int i=0;i<=n;i++)
    {
        pre[i]=i;
    }
    for(int i=1;i<=n;i++)
    {
        e[cnt].d=i;
        cin>>e[cnt].w;
        e[cnt++].s=0;
    }
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    {
        if(i>=j)
        {
            cin>>e[cnt].w;continue;
        }
        e[cnt].s=i;
        cin>>e[cnt].w;
        e[cnt++].d=j;
    }
    sort(e,e+cnt);
    edge t;
    for(int i=0;i<cnt&&c<n;i++)
    {
        t=e[i];
        if(merge(t.s,t.d))//成功
        {
            c++;
            ans+=t.w;
        }
    }
    cout<<ans<<endl;
   // system("pause");
    return 0;
}
to sum up

A typical minimum spanning tree problem, but the idea of ​​this super origin is still learned.

Question D Data Center

Title description

Insert picture description here

样例: 
input
4
5
1
1 2 3
1 3 4
1 4 5
2 3 8
3 4 2  
Output  
4
Ideas

This question is cumbersome, but the problem is still very simple. It requires the largest edge of the smallest spanning tree. The last edge added by Kruskal is the answer. However, the union check here is not simple. Have to use path optimization

Code
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
struct edge
{
    int s,d,w;
    bool operator <(const edge&e)const{
        return w<e.w;
    }
};
int pre[50005] ;
int find(int p)
{
   // return i==pre[i]?i:find(pre[i]); 
            while(p != pre[p])
            {   //如果p元素的父亲指针指向的不是自己,说明p并不是集合中的根元
                //素,还需要一直向上查找和路径压缩
                //在find查询中嵌入一个路径压缩操作
                pre[p]=pre[pre[p]];
                //p元素不再选择原来的父亲节点,而是直接选择父亲节点的父亲节点来做为自己新的一个父亲节点
                //这样的操作使得树的层数被压缩了
                p=pre[p];
                //p压缩完毕后且p并不是根节点,p变成p新的父节点继续进行查找和压缩的同时操作
            }
            return p; 
}
bool merge(int i,int j)
{
    i=find(i);
    j=find(j);
    if(i==j)return 0;
    pre[i]=j; 
    return 1;
}
edge e[100005];
int n,m,root,w,cnt,c,ans,t1,t2,t3;
int main()
{
    scanf("%d%d%d",&n,&m,&root);
    for(int i=0;i<=n;i++)
    pre[i]=i;
    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&e[i].s,&e[i].d,&e[i].w);
    }  
    sort(e,e+m);
    edge t;
    for(int i=0;i<m&&c<n;i++)
    {
        t=e[i];
        if(merge(t.s,t.d))//成功
        {
            c++;
            if(c==n-1)ans=t.w;
        }
    }
    cout<<ans<<endl;
   // system("pause");
    return 0;
}
to sum up

Don't ask me how I know that I want to optimize the path

Published 20 original articles · praised 3 · visits 453

Guess you like

Origin blog.csdn.net/qq_44893580/article/details/105282448