7-1 depth first search I (100 points)
Undirected graph G has n vertices and m edges. Find the depth first search tree (forest) of graph G and the discovery time and completion time of each vertex. Each connected component is searched from the node with the smallest number, and the selection order of adjacent vertices follows the input order of edges.
When a node is encountered for the first time in the search process, it is said that the node is found; All adjacent nodes of a node are searched, and the search of the node is completed. Depth first search maintains a clock. The clock counts from 0. When the node is found or completed, the clock count is increased by 1, and then the time stamp is stamped for the current node. The timestamp of a node being found and completed by search is called the discovery time and completion time of the node respectively
Input format:
In the first line, two integers n and m, separated by spaces, represent the number of vertices and edges respectively, 1 ≤ n ≤ 50000, 1 ≤ m ≤ 100000
Lines 2 to m+1, two integers u and V in each line, separated by spaces, indicate that there is an edge from vertex u to vertex v, u and V are vertex numbers, 1 ≤ u,v ≤ n
Output format:
Lines 1 to N, two integers di and fi in each line, separated by spaces, represent the discovery time and completion time of the ith vertex 1 ≤ i ≤ n.
Line n+1, an integer k, represents the number of edges of the depth first search tree (forest) of the graph.
Lines n+2 to n+k+1, with two integers u and v in each line, represent an edge < u, v > of the depth first search tree (forest), and the output order of the edges is numbered from small to large according to the number of v nodes.
Input sample:
A set of inputs is given here. For example:
6 5
1 3
1 2
2 3
4 5
5 6
Output example:
The corresponding output is given here. For example:
1 6
3 4
2 5
7 12
8 11
9 10
4
3 2
1 3
4 5
5 6
Topic analysis
dfs.
The code implementation is as follows
#include <bits/stdc++.h> using namespace std; int num=1; int arc; int fi[50010],di[50010],visited[50010]; struct cmp{ bool operator ()(pair<int,int> a,pair<int,int> b){ return a.second>b.second; } }; priority_queue<pair<int,int>,vector<pair<int,int> >,cmp> q; vector<int> e[50010]; void dfs(int u){ visited[u]=1; fi[u]=num++; for(int j=0;j<e[u].size();j++){ int v=e[u][j]; if(!visited[v]){ dfs(v); arc++; q.push({u,v}); } } di[u]=num++; return ; } int main() { int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=m;i++){ int x,y; scanf("%d %d",&x,&y); e[x].push_back(y); e[y].push_back(x); } for(int i=1;i<=n;i++){ if(!visited[i]) dfs(i); } for(int i=1;i<=n;i++){ printf("%d %d\n",fi[i],di[i]); } printf("%d\n",arc); while(!q.empty()){ pair<int,int> uv=q.top(); q.pop(); int u=uv.first; int v=uv.second; printf("%d %d\n",u,v); } return 0; }
7-2 circles (100 points)
There are n circles on the two-dimensional plane. Please count the number of different blocks formed by these circles.
The block formed by a circle is defined as follows: (1) a circle is a block; (2) If two blocks have common parts (including tangency), the two blocks form a new block, otherwise they are still two different blocks.
Input format:
The first line includes an integer n, indicating the number of circles, n < = 8000.
Lines 2 to n+1, each with three numbers x, y, r separated by spaces. (x, y) is the center coordinate and r is the radius. All coordinates and radii are non negative integers no greater than 30000.
Output format:
An integer representing the number of blocks formed.
Input sample:
A set of inputs is given here. For example:
2
0 0 1
1 0 2
Output example:
The corresponding output is given here. For example:
1
Topic analysis
That is, investigate and search the set. It is worth noting that when finding the intersection of two circles, the root sign should not be opened. Use three long long type numbers to store the comparison number.
The code implementation is as follows
#include <bits/stdc++.h> using namespace std; struct circle{ int x,y,r; }c[8010]; int mark[8010]; int num; int pan(circle a,circle b){ int x1=a.x,y1=a.y,r1=a.r,x2=b.x,y2=b.y,r2=b.r; long d=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2); long p=r1+r2; p=p*p; if(p>=d)return 1; else return 0; } int main(){ int n; scanf("%d",&n); num=n; for(int i=1;i<=n;i++){ int x0,y0,r0; scanf("%d %d %d",&x0,&y0,&r0); c[i].r=r0; c[i].x=x0; c[i].y=y0; mark[i]=i; } for(int i=1;i<n;i++){ for(int j=i+1;j<=n;j++){ if(pan(c[i],c[j])){ int a,b; a=mark[i]; b=mark[j]; while(a!=mark[a])a=mark[a]; while(b!=mark[b])b=mark[b]; mark[b]=a; } } } for(int i=1;i<=n;i++){ if(mark[i]!=i){ num--; } } printf("%d",num); return 0; }
7-3 power supply (100 points)
To power N regions. Each area may build a power supply station or build a line to connect to other areas with electricity. Try to determine the minimum cost of supplying power to N regions.
Input format:
In the first line, two integers N and M, separated by spaces, represent the number of regions and the number of schemes for line repair respectively, 1 ≤ N ≤ 10000, 0 ≤ M ≤ 50000.
The second line contains N integers P[i] separated by spaces, indicating the cost of building a power supply station in the ith area, 1 ≤ P[i] ≤ 100000, 1 ≤ I ≤ N.
The next M lines are 3 integers a,b and c in each line, separated by spaces, indicating that the cost of building a line between areas a and b is c, 1 ≤ c ≤ 100000, 1 ≤ a,b ≤ N.
Output format:
A line containing an integer representing the minimum cost.
Input sample:
A set of inputs is given here. For example:
4 6
5 4 4 3
1 2 2
1 3 2
1 4 2
2 3 3
2 4 3
3 4 4
Output example:
The corresponding output is given here. For example:
9
Topic analysis
Each power supply station can write its own to its own side, take the point with the least weight as the starting point, and use prim algorithm.
The code implementation is as follows
#include <bits/stdc++.h> using namespace std; #define max 100010 int lowcost[max]; int mark[max]; long long sum; vector<pair<long,int> >e[max]; void prim(int st,int n){ mark[st]=1; for(int i=0;i<e[st].size();i++){ pair<long,int> wv=e[st][i]; long w=wv.first; int v=wv.second; if(lowcost[v]>w)lowcost[v]=w; } for(int i=1;i<n;i++){ int r=max,u=0; for(int j=1;j<=n;j++){ if(lowcost[j]<r&&!mark[j]){ r=lowcost[j]; u=j; } } mark[u]=1; for(int l=0;l<e[u].size();l++){ pair<long,int> wv=e[u][l]; long w=wv.first; int v=wv.second; if(lowcost[v]>w&&!mark[v]){ lowcost[v]=w; } } } return ; } int main(){ int n,m,min=0; lowcost[min]=max; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++){ int x; scanf("%d",&x); lowcost[i]=x; if(lowcost[min]>lowcost[i])min=i; } for(int i=1;i<=m;i++){ int u,v,w; scanf("%d %d %d",&u,&v,&w); e[u].push_back({w,v}); e[v].push_back({w,u}); } prim(min,n); for(int i=1;i<=n;i++)sum+=lowcost[i]; printf("%lld\n",sum); return 0; }
7-4 red envelopes (100 points)
When the new year comes, the company will send red envelopes to employees. Employees will compare the amount of red envelopes they receive. Some employees will ask for the amount of money. For example, the amount of red envelopes in c1 is more than that in c2. The amount of red envelope money for each employee should be at least 888 yuan, which is a lucky number.
The company wants to meet the requirements of all employees and spend the least money at the same time. Please help calculate.
Input format:
In line 1, two integers n and m (n < = 10000, m < = 20000), separated by spaces, represent the number of employees and the required number respectively.
The next m lines are two integers c1 and c2, separated by spaces, indicating that the number of red envelopes of employee c1 is more than c2, and the employee number is 1~n.
Output format:
An integer that represents the minimum amount of money the company sends. If the company cannot meet the needs of all employees, output - 1
Input sample:
A set of inputs is given here. For example:
2 1
1 2
Output example:
The corresponding output is given here. For example:
1777
Topic analysis
It is easy to see that it is a topological order.
The code implementation is as follows
#include <bits/stdc++.h> using namespace std; #define max 10010 int s[max]; int counter[max]; int sum; vector<int> e[max]; queue<int> q; int topo(int n){ for(int i=1;i<=n;i++){ for(int j=0;j<e[i].size();j++){ int v=e[i][j]; counter[v]++; } } for(int i=1;i<=n;i++){ if(counter[i])continue; else {q.push(i);s[i]=888;sum+=s[i];} } for(int i=1;i<=n;i++){ int t=q.front(); q.pop(); for(int j=0;j<e[t].size();j++){ int v=e[t][j]; counter[v]--; if(counter[v])continue; else {q.push(v);s[v]=s[t]+1;sum+=s[v];} } } if(q.empty())return 1; else return 0; } int main(){ int n,m; scanf("%d %d",&n,&m); for(int i=0;i<m;i++){ int u,v; scanf("%d %d",&u,&v); e[u].push_back(v); } if(topo(n)) printf("%d",sum); else printf("-1"); }