PTA图论的搜索题

目录

7-1 列出连通集

题目

输入格式:

输出格式:

输入样例:

输出样例:

AC代码

7-2 六度空间

题目

输入格式:

输出格式:

输入样例:

输出样例:

思路

AC代码

7-3 地下迷宫探索

题目

输入格式:

输出格式:

输入样例1:

输出样例1:

输入样例2:

输出样例2:

思路

AC代码

7-4 社交网络图中结点的“重要性”计算

题目

输入格式:

输出格式:

输入样例:

输出样例:

思路

AC代码

7-5 List Components

题目

Input Specification:

Output Specification:

Sample Input:

Sample Output:

思路

AC代码

7-6 排座位

题目

输入格式:

输出格式:

输入样例:

输出样例:

思路

AC代码

7-7 红色警报

题目

输入格式:

输出格式:

输入样例:

输出样例:

思路

AC代码

7-8 家庭房产

题目

输入格式:

输出格式:

输入样例:

输出样例:

思路

AC代码

7-9 肿瘤诊断

题目

输入格式:

输出格式:

输入样例:

输出样例:

思路

AC代码(BFS)

没有AC的代码(调了很久,还是2/30)。

7-10 图着色问题

题目

输入格式:

输出格式:

输入样例:

输出样例:

思路

AC代码

7-11 拯救007

输入格式:

输出格式:

输入样例 1:

输出样例 1:

输入样例 2:

输出样例 2:

思路

AC代码


7-1 列出连通集

题目

分数 25

作者 陈越

单位 浙江大学

给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入格式:

输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。

输出格式:

按照"{ v1​ v2​ ... vk​ }"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。

输入样例:

8 6
0 7
0 1
2 0
4 1
2 4
3 5

输出样例:

{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

AC代码

#include<iostream>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
int mat[11][11];
bool visited[12];
vector<int> v;
void dfs(int cur,int n)
{visited[cur]=true;v.push_back(cur);for(int i=0;i<n;i++){if(visited[i]==true||i==cur)continue;if(mat[cur][i]==1)dfs(i,n);}
}
void bfs(int cur,int n)
{queue<int> Q;Q.push(cur);visited[cur]=true;v.push_back(cur);//v存放cur所在的连通集while(!Q.empty()){int k=Q.size();for(int i=0;i<k;i++){//取队头元素的所有直接联通点for(int j=0;j<n;j++){if(visited[j]==true||Q.front()==j)continue;if(mat[Q.front()][j]==1){Q.push(j);visited[j]=true;v.push_back(j);}}Q.pop();}}
}
int main()
{int n,e;cin>>n>>e;for(int i=0;i<e;i++){int a,b;cin>>a>>b;mat[a][b]=mat[b][a]=1;}memset(visited,false,sizeof(visited)/sizeof(bool));//dfsfor(int i=0;i<n;i++){v.resize(0);if(visited[i]==false)dfs(i,n);for(int j=0;j<v.size();j++){if(j==0)cout<<"{ ";cout<<v[j]<<" ";if(j==v.size()-1)cout<<"}\n";}}//bfsmemset(visited,false,sizeof(visited)/sizeof(bool));for(int i=0;i<n;i++){v.resize(0);if(visited[i]==false)bfs(i,n);for(int j=0;j<v.size();j++){if(j==0)cout<<"{ ";cout<<v[j]<<" ";if(j==v.size()-1)cout<<"}\n";}}
}

7-2 六度空间

题目

分数 30

作者 DS课程组

单位 浙江大学

“六度空间”理论又称作“六度分隔(Six Degrees of Separation)”理论。这个理论可以通俗地阐述为:“你和任何一个陌生人之间所间隔的人不会超过六个,也就是说,最多通过五个人你就能够认识任何一个陌生人。”如图1所示。


图1 六度空间示意图

“六度空间”理论虽然得到广泛的认同,并且正在得到越来越多的应用。但是数十年来,试图验证这个理论始终是许多社会学家努力追求的目标。然而由于历史的原因,这样的研究具有太大的局限性和困难。随着当代人的联络主要依赖于电话、短信、微信以及因特网上即时通信等工具,能够体现社交网络关系的一手数据已经逐渐使得“六度空间”理论的验证成为可能。

假如给你一个社交网络图,请你对每个节点计算符合“六度空间”理论的结点占结点总数的百分比。

输入格式:

输入第1行给出两个正整数,分别表示社交网络图的结点数N(1<N≤103,表示人数)、边数M(≤33×N,表示社交关系数)。随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个结点的编号(节点从1到N编号)。

输出格式:

对每个结点输出与该结点距离不超过6的结点数占结点总数的百分比,精确到小数点后2位。每个结节点输出一行,格式为“结点编号:(空格)百分比%”。

输入样例:

10 9
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10

输出样例:

1: 70.00%
2: 80.00%
3: 90.00%
4: 100.00%
5: 100.00%
6: 100.00%
7: 100.00%
8: 90.00%
9: 80.00%
10: 70.00%

代码长度限制

16 KB

时间限制

2500 ms

内存限制

64 MB

思路

广度优先搜索,通过几层的搜索能找到另一人就是两个人之间的间隔。

AC代码

这题是刚学数据结构时写的,里面有一些复杂的结构。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define MVNum 1000
#define Maxint 32767
using namespace std;
bool visited[MVNum];
typedef int VerTexType;
typedef int ArcType;//邻接表
typedef struct ArcNode {//边 int adjvex;  //边所指向顶点的位置 struct ArcNode* nextarc; //下一个边 
}ArcNode;
typedef struct VNode {//顶点 VerTexType date;ArcNode* firstarc;
}VNode, AdjList[MVNum];
typedef struct {  //邻接表 AdjList vertices;int vexnum, arcnum;
}ALGraph;void CreateUDG(ALGraph& G)
{//创建无向图的邻接表 cin >> G.vexnum >> G.arcnum;//顶点赋初值 for (int i = 0; i < G.vexnum; i++){G.vertices[i].date = i + 1;G.vertices[i].firstarc = NULL;}for (int k = 0; k < G.arcnum; k++){int i, j;cin >> i >> j;i--;j--;ArcNode* p1, * p2;//i邻接一条边j p1 = new ArcNode;p1->adjvex = j;p1->nextarc = G.vertices[i].firstarc;G.vertices[i].firstarc = p1;//j邻接一条边ip2 = new ArcNode;p2->adjvex = i;p2->nextarc = G.vertices[j].firstarc;G.vertices[j].firstarc = p2;}
}
double BFS_AL(ALGraph& G, int v)
{//从下标为V的点开始广度优先搜索,对邻接表 
//	cout << "从下标" << v << "开始查找:";int friends = 0;int step = 0;//节点之间的距离 memset(visited, false, sizeof(bool) * G.vexnum);queue<VNode>Q;  //队列的元素是邻接表的点,不是邻接表边Q.push(G.vertices[v]);visited[v] = true;while (!Q.empty() && step < 6){step++;
//		cout << "\n第" << step << "步访问的下标:";//取队里的所有点,并将这些元素的未标记的邻接点放进队列int n = Q.size();for (int i = 0; i < n; i++){VNode p = Q.front();Q.pop();//找出队元素所有未被访问的邻接点 (即找某个人的所有朋友)ArcNode* q = p.firstarc;while (q != NULL){if (visited[q->adjvex] == false){visited[q->adjvex] = true;Q.push(G.vertices[q->adjvex]);}q = q->nextarc;}}}//while//计算比例 ,六步之内找到的朋友(包括自己)/总人数 for (int i = 0; i < G.vexnum; i++)if (visited[i] == true) friends++;
//	cout << "vexnum=" << G.vexnum << "  " << "friends=" << friends << "  ";return 1.0 * friends / G.vexnum;
}int main()
{ALGraph G;CreateUDG(G);for (int i = 0; i < G.vexnum; i++){double a = 100 * BFS_AL(G, i);printf("%d: %.2lf%%\n", i + 1, a);}return 0;
}

7-3 地下迷宫探索

题目

分数 30

作者 DS课程组

单位 浙江大学

地道战是在抗日战争时期,在华北平原上抗日军民利用地道打击日本侵略者的作战方式。地道网是房连房、街连街、村连村的地下工事,如下图所示。

我们在回顾前辈们艰苦卓绝的战争生活的同时,真心钦佩他们的聪明才智。在现在和平发展的年代,对多数人来说,探索地下通道或许只是一种娱乐或者益智的游戏。本实验案例以探索地下通道迷宫作为内容。

假设有一个地下通道迷宫,它的通道都是直的,而通道所有交叉点(包括通道的端点)上都有一盏灯和一个开关。请问你如何从某个起点开始在迷宫中点亮所有的灯并回到起点?

输入格式:

输入第一行给出三个正整数,分别表示地下迷宫的节点数N(1<N≤1000,表示通道所有交叉点和端点)、边数M(≤3000,表示通道数)和探索起始节点编号S(节点从1到N编号)。随后的M行对应M条边(通道),每行给出一对正整数,分别是该条边直接连通的两个节点的编号。

输出格式:

若可以点亮所有节点的灯,则输出从S开始并以S结束的包含所有节点的序列,序列中相邻的节点一定有边(通道);否则虽然不能点亮所有节点的灯,但还是输出点亮部分灯的节点序列,最后输出0,此时表示迷宫不是连通图。

由于深度优先遍历的节点序列是不唯一的,为了使得输出具有唯一的结果,我们约定以节点小编号优先的次序访问(点灯)。在点亮所有可以点亮的灯后,以原路返回的方式回到起点。

输入样例1:

6 8 1
1 2
2 3
3 4
4 5
5 6
6 4
3 6
1 5

输出样例1:

1 2 3 4 5 6 5 4 3 2 1

输入样例2:

6 6 6
1 2
1 3
2 3
5 4
6 5
6 4

输出样例2:

6 4 5 4 6 0

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

思路

深度优先搜索。但是这题并不是说每个节点只遍历一次,而是说在遍历完所有的节点的过程中,访问某个节点和访问完这个节点回溯时都要打印一次。

AC代码

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int SIZE = 1005;
int N, M, S;
int cnt = 0; //记录输出的数量,防止多输出空格
vector<vector<int>> arc;
vector<int> path;
int visited[SIZE];
void inif()
{arc.resize(N + 1);for (int i = 0; i < M; i++){int arc1, arc2;cin >> arc1 >> arc2;arc[arc1].push_back(arc2);arc[arc2].push_back(arc1);}//排序,优先访问序列小的节点for (int i = 1; i <= N; i++){sort(arc[i].begin(), arc[i].end());}
}
void dfs(int i)
{visited[i] = 1;cnt++;//点灯时输出一次if (cnt == 1) cout << i;else cout << " " << i;for (int j = 0; j < arc[i].size(); j++){if (visited[arc[i][j]] == 0){dfs(arc[i][j]);//点完相邻的灯后输出一次cout << " " << i;}}
}
int main()
{cin >> N >> M >> S;inif();dfs(S);if(cnt!=N) cout<<" 0";
}

7-4 社交网络图中结点的“重要性”计算

题目

分数 30

作者 DS课程组

单位 浙江大学

在社交网络中,个人或单位(结点)之间通过某些关系(边)联系起来。他们受到这些关系的影响,这种影响可以理解为网络中相互连接的结点之间蔓延的一种相互作用,可以增强也可以减弱。而结点根据其所处的位置不同,其在网络中体现的重要性也不尽相同。

“紧密度中心性”是用来衡量一个结点到达其它结点的“快慢”的指标,即一个有较高中心性的结点比有较低中心性的结点能够更快地(平均意义下)到达网络中的其它结点,因而在该网络的传播过程中有更重要的价值。在有N个结点的网络中,结点vi​的“紧密度中心性”Cc(vi​)数学上定义为vi​到其余所有结点vj​ (j=i) 的最短距离d(vi​,vj​)的平均值的倒数:

对于非连通图,所有结点的紧密度中心性都是0。

给定一个无权的无向图以及其中的一组结点,计算这组结点中每个结点的紧密度中心性。

输入格式:

输入第一行给出两个正整数N和M,其中N(≤104)是图中结点个数,顺便假设结点从1到N编号;M(≤105)是边的条数。随后的M行中,每行给出一条边的信息,即该边连接的两个结点编号,中间用空格分隔。最后一行给出需要计算紧密度中心性的这组结点的个数K(≤100)以及K个结点编号,用空格分隔。

输出格式:

按照Cc(i)=x.xx的格式输出K个给定结点的紧密度中心性,每个输出占一行,结果保留到小数点后2位。

输入样例:

9 14
1 2
1 3
1 4
2 3
3 4
4 5
4 6
5 6
5 7
5 8
6 7
6 8
7 8
7 9
3 3 4 9

输出样例:

Cc(3)=0.47
Cc(4)=0.62
Cc(9)=0.35

代码长度限制

16 KB

时间限制

20000 ms

内存限制

64 MB

思路

用广度优先搜索计算某个点到其他点的距离。其间用一个数记录联通点的数量,若联通点的数量不等于N,就全输出0。

AC代码

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int MAXSIZE=10005;
int N,M,K;
vector<vector<int>> f;   //用于记忆化
vector<vector<int>> arcs; //邻接表
int visited[MAXSIZE];
bool flag=true;  //标志是否连通
int cnt=0;      //联通点的数量
void inif()
{cin>>N>>M;arcs.resize(N+1);for(int i=0;i<M;i++){int arc1,arc2;cin>>arc1>>arc2;arcs[arc1].push_back(arc2);arcs[arc2].push_back(arc1);}
}
void MEMSET(){for(int i=1;i<=N;i++) visited[i]=0;}
long long bfs(int x)
{if(!flag) return -1;MEMSET();long long sum=0;int length=0;//点x到某个点的长度queue<int> q;q.push(x);visited[x]=1;cnt=1;while(!q.empty()){int size=q.size();++length;for(int i=0;i<size;i++){int cur=q.front();q.pop();for(auto arc:arcs[cur]){if(visited[arc]==0){q.push(arc);++cnt;visited[arc]=1;sum+=length;}}}}if(cnt!=N){flag=false;return -1;}return sum;
}
void slove()
{cin>>K;for(int i=0;i<K;i++){if(i!=0) cout<<endl;int x;cin>>x;if(!flag){cout<<"Cc("<<x<<")=0.00";continue;}double aver=1.0*(N-1)/bfs(x);if(!flag){cout<<"Cc("<<x<<")=0.00";continue;}printf("Cc(%d)=%.2lf",x,aver);}
}
int main()
{inif();slove();
}

7-5 List Components

题目

分数 25

作者 陈越

单位 浙江大学

For a given undirected graph with N vertices and E edges, please list all the connected components by both DFS (Depth First Search) and BFS (Breadth First Search). Assume that all the vertices are numbered from 0 to N-1. While searching, assume that we always start from the vertex with the smallest index, and visit its adjacent vertices in ascending order of their indices.

Input Specification:

Each input file contains one test case. For each case, the first line gives two integers N (0<N≤10) and E, which are the number of vertices and the number of edges, respectively. Then E lines follow, each described an edge by giving the two ends. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in each line a connected component in the format { v1​ v2​ ... vk​ }. First print the result obtained by DFS, then by BFS.

Sample Input:

8 6
0 7
0 1
2 0
4 1
2 4
3 5

Sample Output:

{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

思路

这是一个英文题,稍微阅读一下然后和7-1的输入输出对比一下会发现,这题就是7-1的英文版。

AC代码

#include<iostream>
#include<queue>
using namespace std;
int f[15][15];
int visited[15];
int N, E;
vector<int> g;
int flag = false;
void dfs(int i)
{for (int j = 0; j < N; j++) {if (f[i][j] == 1 && visited[j] == 0) {g.push_back(j);visited[j] = 1;dfs(j);}}
}
void bfs(int i)
{queue<int> q;q.push(i);g.push_back(i);visited[i] = 1;while (!q.empty()) {int cur = q.front();q.pop();for (int j = 0; j < N; j++) {if (f[cur][j] == 1 && visited[j] == 0) {visited[j] = 1;g.push_back(j);q.push(j);}}}
}
int main()
{cin >> N >> E;for (int i = 0; i < E; i++) {int x, y;cin >> x >> y;f[x][y] = f[y][x] = 1;}for (int i = 0; i < N; i++) {if (visited[i] == 0) {visited[i] = 1;g.resize(0);g.push_back(i);dfs(i);if (flag == true) cout << endl;flag = true;cout << "{ ";for (int j = 0; j < g.size(); j++) {cout << g[j] << " ";}cout << "}";}}for (int i = 0; i < N; i++) visited[i] = 0;for (int i = 0; i < N; i++) {if (visited[i] == 0) {g.resize(0);bfs(i);if (flag == true) cout << endl;flag = true;cout << "{ ";for (int j = 0; j < g.size(); j++) {cout << g[j] << " ";}cout << "}";}}
}

7-6 排座位

题目

分数 25

作者 陈越

单位 浙江大学

布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位。无论如何,总不能把两个死对头排到同一张宴会桌旁!这个艰巨任务现在就交给你,对任何一对客人,请编写程序告诉主人他们是否能被安排同席。

输入格式:

输入第一行给出3个正整数:N(≤100),即前来参宴的宾客总人数,则这些人从1到N编号;M为已知两两宾客之间的关系数;K为查询的条数。随后M行,每行给出一对宾客之间的关系,格式为:宾客1 宾客2 关系,其中关系为1表示是朋友,-1表示是死对头。注意两个人不可能既是朋友又是敌人。最后K行,每行给出一对需要查询的宾客编号。

这里假设朋友的朋友也是朋友。但敌人的敌人并不一定就是朋友,朋友的敌人也不一定是敌人。只有单纯直接的敌对关系才是绝对不能同席的。

输出格式:

对每个查询输出一行结果:如果两位宾客之间是朋友,且没有敌对关系,则输出No problem;如果他们之间并不是朋友,但也不敌对,则输出OK;如果他们之间有敌对,然而也有共同的朋友,则输出OK but...;如果他们之间只有敌对关系,则输出No way

输入样例:

7 8 4
5 6 1
2 7 -1
1 3 1
3 4 1
6 7 -1
1 2 1
1 4 1
2 3 -1
3 4
5 7
2 3
7 2

输出样例:

No problem
OK
OK but...
No way

代码长度限制

16 KB

时间限制

200 ms

内存限制

64 MB

思路

并查集判断两个人是否是朋友(的朋友的朋友的朋友……)。

AC代码

#include<iostream>
using namespace std;
const int MAXSIZE = 105;
int N, M, K;
int relation[MAXSIZE][MAXSIZE];
int fa[MAXSIZE * MAXSIZE];
int find(int x)
{int r = x;while (fa[r] != r){fa[r] = fa[fa[r]];r = fa[r];}return r;
}
void merge(int x, int y)
{int fx = find(x);int fy = find(y);if (fx > fy) {fa[fy] = fx;}else {fa[fx] = fy;}
}
int node(int i, int j) { return N * (i - 1) + j; }
void inif()
{cin >> N >> M >> K;for (int i = 1; i <= N; i++) {fa[i] = i;for (int j = 1; j <= N; j++) {relation[i][j] = 0;}}for (int i = 0; i < M; i++){int x, y, c;cin >> x >> y >> c;relation[x][y] = relation[y][x] = c;if (c == 1) merge(x, y);}
}
void slove()
{for (int i = 0; i < K; i++){if (i != 0) cout << endl;int x, y;cin >> x >> y;bool flag = (find(x) == find(y));if (flag && relation[x][y] != -1) cout << "No problem";else if (!flag && relation[x][y] != -1) cout << "OK";else if (flag && relation[x][y] == -1) cout << "OK but...";else cout << "No way";}
}
int main()
{inif();slove();
}

7-7 红色警报

题目

分数 25

作者 陈越

单位 浙江大学

战争中保持各个城市间的连通性非常重要。本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报。注意:若该国本来就不完全连通,是分裂的k个区域,而失去一个城市并不改变其他城市之间的连通性,则不要发出警报。

输入格式:

输入在第一行给出两个整数N(0 < N ≤ 500)和M(≤ 5000),分别为城市个数(于是默认城市从0到N-1编号)和连接两城市的通路条数。随后M行,每行给出一条通路所连接的两个城市的编号,其间以1个空格分隔。在城市信息之后给出被攻占的信息,即一个正整数K和随后的K个被攻占的城市的编号。

注意:输入保证给出的被攻占的城市编号都是合法的且无重复,但并不保证给出的通路没有重复。

输出格式:

对每个被攻占的城市,如果它会改变整个国家的连通性,则输出Red Alert: City k is lost!,其中k是该城市的编号;否则只输出City k is lost.即可。如果该国失去了最后一个城市,则增加一行输出Game Over.

输入样例:

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

输出样例:

City 1 is lost.
City 2 is lost.
Red Alert: City 0 is lost!
City 4 is lost.
City 3 is lost.
Game Over.

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

思路

构建好图后先记录一次连通集个数。随后每删除一个点就更新一次连通集个数。若连通集个数没变或只是减了一个,则说明没有改变整个国家的连通性。

AC代码

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int MAXSIZE = 505;
int N, M, K;
vector<vector<int>> g;
int book[MAXSIZE];
int lost[MAXSIZE];//==1表示已经失去
int unionCount = 0;
int func()
{int sum = 0;for (int i = 0; i < N; i++) book[i] = 0;for (int i = 0; i < N; i++) {if (book[i] == 1 || lost[i] == 1) continue;sum++;queue<int> q;q.push(i);while (!q.empty()) {int cur = q.front();q.pop();for (int j = 0; j < g[cur].size(); j++) {int node = g[cur][j];if (lost[node] == 1 || book[node] == 1) continue;q.push(node);book[node] = 1;}}}return sum;
}
void slove()
{cin >> K;int aim;for (int i = 0; i < K; i++) {cin >> aim;if (i != 0) cout << endl;lost[aim] = 1;int cnt = func();if (cnt == unionCount || cnt == unionCount - 1) {cout << "City " << aim << " is lost.";}else {cout << "Red Alert: City " << aim << " is lost!";}unionCount = cnt;//更新if (i == N - 1) {cout << "\nGame Over.";}}
}
int main()
{cin >> N >> M;g.resize(N);for (int i = 0; i < M; i++) {int x, y;cin >> x >> y;g[x].push_back(y);g[y].push_back(x);}unionCount = func();slove();//cout << unionCount;
}

7-8 家庭房产

题目

分数 25

作者 陈越

单位 浙江大学

给定每个人的家庭成员和其自己名下的房产,请你统计出每个家庭的人口数、人均房产面积及房产套数。

输入格式:

输入第一行给出一个正整数N(≤1000),随后N行,每行按下列格式给出一个人的房产:

编号 父 母 k 孩子1 ... 孩子k 房产套数 总面积

其中编号是每个人独有的一个4位数的编号;分别是该编号对应的这个人的父母的编号(如果已经过世,则显示-1);k(0≤k≤5)是该人的子女的个数;孩子i是其子女的编号。

输出格式:

首先在第一行输出家庭个数(所有有亲属关系的人都属于同一个家庭)。随后按下列格式输出每个家庭的信息:

家庭成员的最小编号 家庭人口数 人均房产套数 人均房产面积

其中人均值要求保留小数点后3位。家庭信息首先按人均面积降序输出,若有并列,则按成员编号的升序输出。

输入样例:

10
6666 5551 5552 1 7777 1 100
1234 5678 9012 1 0002 2 300
8888 -1 -1 0 1 1000
2468 0001 0004 1 2222 1 500
7777 6666 -1 0 2 300
3721 -1 -1 1 2333 2 150
9012 -1 -1 3 1236 1235 1234 1 100
1235 5678 9012 0 1 50
2222 1236 2468 2 6661 6662 1 300
2333 -1 3721 3 6661 6662 6663 1 100

输出样例:

3
8888 1 1.000 1000.000
0001 15 0.600 100.000
5551 4 0.750 100.000

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

思路

这题要是一开始就告诉你出现过的人有几个并且所有人的编号都为1-N,那么这题就不难。难点就是所有人的编号是离散的,就要一些特殊处理。

我们用并查集来判断家庭的个数,每次合并两个人的时候,将编号大的指向编号小的。这样统计面积的时候就只需要将每个点的面积属性加到father数组的根当中即可。最后将家庭按照面积降序、最小编号升序的方式排序,然后输出。

AC代码

#include<bits/stdc++.h>
using namespace std;
const int MAXSIZE=1e5+5;
int N;
int family=0;
int fa[MAXSIZE];
bool visited[MAXSIZE];
struct new_person{int id,fid,mid,num,area,k;int child[6];
} g[1005];
struct _ans{int minid=0,people=0;double num=0,area=0;bool have=false;
} ans[MAXSIZE];
bool cmp(_ans a,_ans b)
{if(a.area==b.area)return a.minid<b.minid;return a.area>b.area;
}
int find(int x)
{int r=x;while(fa[r]!=r) r=fa[r];return r;
}
void merge(int x,int y)
{int fx=find(x);int fy=find(y);if(fx<fy) fa[fy]=fx;else if(fx>fy) fa[fx]=fy;
}
int main()
{cin>>N;for(int i=0;i<MAXSIZE;i++) fa[i]=i;//处理输入数据for(int i=0;i<N;i++){cin>>g[i].id>>g[i].fid>>g[i].mid>>g[i].k;visited[g[i].id]=true;if(g[i].fid!=-1){visited[g[i].fid]=true;merge(g[i].id,g[i].fid);}if(g[i].mid!=-1){visited[g[i].mid]=true;merge(g[i].id,g[i].mid);}for(int j=0;j<g[i].k;j++){cin>>g[i].child[j];visited[g[i].child[j]]=true;merge(g[i].id,g[i].child[j]);}cin>>g[i].num>>g[i].area;}//统计房产和每个家庭最小idfor(int i=0;i<N;i++){int j=find(g[i].id);ans[j].minid=j;ans[j].num+=g[i].num;  //房产个数ans[j].area+=g[i].area;  //房产面积 ans[j].have=true;}//统计每个家庭人数和家庭个数for(int i=0;i<10000;i++){if(visited[i]) ans[find(i)].people++;if(ans[i].have) family++;}//将房产个数和房产面积转换为平均值for(int i=0;i<10000;i++){if(ans[i].have){ans[i].num=(double)(1.0*ans[i].num/ans[i].people);ans[i].area=(double)(1.0*ans[i].area/ans[i].people);}}//排序并输出sort(ans,ans+10000,cmp);cout<<family;for(int i=0;i<family;i++){printf("\n%04d %d %.3lf %.3lf",ans[i].minid,ans[i].people,ans[i].num,ans[i].area);}
}

7-9 肿瘤诊断

题目

分数 30

作者 陈越

单位 浙江大学

在诊断肿瘤疾病时,计算肿瘤体积是很重要的一环。给定病灶扫描切片中标注出的疑似肿瘤区域,请你计算肿瘤的体积。

输入格式:

输入第一行给出4个正整数:M、N、L、T,其中M和N是每张切片的尺寸(即每张切片是一个M×N的像素矩阵。最大分辨率是1286×128);L(≤60)是切片的张数;T是一个整数阈值(若疑似肿瘤的连通体体积小于T,则该小块忽略不计)。

最后给出L张切片。每张用一个由0和1组成的M×N的矩阵表示,其中1表示疑似肿瘤的像素,0表示正常像素。由于切片厚度可以认为是一个常数,于是我们只要数连通体中1的个数就可以得到体积了。麻烦的是,可能存在多个肿瘤,这时我们只统计那些体积不小于T的。两个像素被认为是“连通的”,如果它们有一个共同的切面,如下图所示,所有6个红色的像素都与蓝色的像素连通。

输出格式:

在一行中输出肿瘤的总体积。

输入样例:

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

输出样例:

26

代码长度限制

16 KB

时间限制

1000 ms

内存限制

64 MB

思路

刚开始看不懂题目什么意思,后面发现,就是一个图结构,要我们判断所有体积大于T的连通块。

但是以往的邻接矩阵都是二维的,有四个方向。这次是三维的,有六个方向。

AC代码(BFS)

#include<iostream>
#include<queue>
using namespace std;
int M, N, L, T;
struct Node {int x, y, z;
};
int dx[6] = { 1,-1,0,0,0,0 };
int dy[6] = { 0,0,1,-1,0,0 };
int dz[6] = { 0,0,0,0,1,-1 };
int f[1300][130][70];
int book[1300][130][70];
int sum = 0;
int bfs(int x, int y, int z)
{int ans = 1;queue<Node> q;q.push({ x,y,z });while (!q.empty()) {Node node = q.front();q.pop();//遍历六个方向for (int i = 0; i < 6; i++) {int new_x = node.x + dx[i];int new_y = node.y + dy[i];int new_z = node.z + dz[i];if (new_x < 0 || new_x >= M || new_y < 0 || new_y >= N || new_z < 0 || new_z >= L || book[new_x][new_y][new_z] == 1 || f[new_x][new_y][new_z] == 0)continue;ans++;book[new_x][new_y][new_z] = 1;q.push({ new_x,new_y,new_z });}}if (ans >= T) return ans;else return 0;
}
int main()
{cin >> M >> N >> L >> T;for (int i = 0; i < L; i++)for (int j = 0; j < M; j++)for (int k = 0; k < N; k++)cin >> f[j][k][i];for (int i = 0; i < L; i++)for (int j = 0; j < M; j++)for (int k = 0; k < N; k++)if (f[j][k][i] == 1 && book[j][k][i] == 0) {book[j][k][i] = 1;sum += bfs(j, k, i);}cout << sum << endl;return 0;
}

没有AC的代码(调了很久,还是2/30)。

只有一个点2分,其他点都是运行超时或者内存超限。将BFS的倒数第七句的[tz][tz][ty]改成[tz][tx][ty]还是只有6分。又发现错误的大佬可以指正一下。

#include<iostream>
#include<queue>
#include<vector>
using namespace std;
int M, N, L, T;
int f[61][1287][130];
bool visited[61][1287][130];
//上下前后左右六个方向
int dx[6] = { 0,0,-1,1,0,0 };
int dy[6] = { 0,0,0,0,-1,1 };
int dz[6] = { -1,1,0,0,0,0 };
struct coord {int x, y, z;
};
int bfs(int x_, int y_, int z_)
{int ans = 1;queue<coord> q;//{z,x,y}coord p = { x_,y_,z_ };q.push(p);visited[z_][x_][y_] = 1;while (!q.empty()) {coord cur = q.front();q.pop();int x = cur.x;int y = cur.y;int z = cur.z;for (int i = 0; i < 6; i++) {int tx = x + dx[i];int ty = y + dy[i];int tz = z + dz[i];if (tx >= 0 && tx < M && ty >= 0 && ty < N && tz >= 0 && tz < L && visited[tz][tx][ty] == false && f[tz][tx][ty] == 1) {coord adj = { tx,ty,tz };q.push(adj);visited[tz][tz][ty] = 1;ans++;}}}return ans;
}
int main()
{cin >> M >> N >> L >> T;for (int i = 0; i < L; i++) {for (int j = 0; j < M; j++) {for (int k = 0; k < N; k++) {cin >> f[i][j][k];}}}int sum = 0;/*int sum1 = sizeof(f) / sizeof(int);int sum2 = sizeof(visited) / sizeof(int);cout << sum1 << endl << sum2 << endl;*/for (int i = 0; i < L; i++) {for (int j = 0; j < M; j++) {for (int k = 0; k < N; k++) {if (visited[i][j][k] == 1 || f[i][j][k] == 0) continue;int v = bfs(i, j, k);sum += (v >= T ? v : 0);}}}cout << sum;
}

7-10 图着色问题

题目

分数 25

作者 陈越

单位 浙江大学

图着色问题是一个著名的NP完全问题。给定无向图G=(V,E),问可否用K种颜色为V中的每一个顶点分配一种颜色,使得不会有两个相邻顶点具有同一种颜色?

但本题并不是要你解决这个着色问题,而是对给定的一种颜色分配,请你判断这是否是图着色问题的一个解。

输入格式:

输入在第一行给出3个整数V(0<V≤500)、E(≥0)和K(0<K≤V),分别是无向图的顶点数、边数、以及颜色数。顶点和颜色都从1到V编号。随后E行,每行给出一条边的两个端点的编号。在图的信息给出之后,给出了一个正整数N(≤20),是待检查的颜色分配方案的个数。随后N行,每行顺次给出V个顶点的颜色(第i个数字表示第i个顶点的颜色),数字间以空格分隔。题目保证给定的无向图是合法的(即不存在自回路和重边)。

输出格式:

对每种颜色分配方案,如果是图着色问题的一个解则输出Yes,否则输出No,每句占一行。

输入样例:

6 8 3
2 1
1 3
4 6
2 5
2 4
5 4
5 6
3 6
4
1 2 3 3 1 2
4 5 6 6 4 5
1 2 3 4 5 6
2 3 4 2 3 4

输出样例:

Yes
Yes
No
No

代码长度限制

16 KB

时间限制

300 ms

内存限制

64 MB

思路

以此判断每个点是否有颜色相同的相邻点。甚至不用搜索。

关键点是每一个方案颜色只能有K种(刚好K种)。

AC代码

//只用k种颜色,不多不少
#include<iostream>
#include<vector>
#include<map>
#include<queue>
using namespace std;
int V,E,K;
vector<vector<int>> g;
int color[502];
int main()
{cin>>V>>E>>K;g.resize(V+1);for(int i=0;i<E;i++){int x,y;cin>>x>>y;g[x].emplace_back(y);g[y].emplace_back(x);}int n;cin>>n;while(n--){map<int,int> mp;for(int i=1;i<=V;i++){cin>>color[i];mp[color[i]]++;}int color_cnt=mp.size();if(color_cnt!=K){cout<<"No\n";continue;}bool flag=true;for(int i=1;i<=V;i++){for(int j=0;j<g[i].size();j++){if(color[i]==color[g[i][j]]){flag=false;goto loop;}}}loop:;if(flag) cout<<"Yes\n";else cout<<"No\n";}
}

7-11 拯救007

分数 25

作者 陈越

单位 浙江大学

在老电影“007之生死关头”(Live and Let Die)中有一个情节,007被毒贩抓到一个鳄鱼池中心的小岛上,他用了一种极为大胆的方法逃脱 —— 直接踩着池子里一系列鳄鱼的大脑袋跳上岸去!(据说当年替身演员被最后一条鳄鱼咬住了脚,幸好穿的是特别加厚的靴子才逃过一劫。)

设鳄鱼池是长宽为100米的方形,中心坐标为 (0, 0),且东北角坐标为 (50, 50)。池心岛是以 (0, 0) 为圆心、直径15米的圆。给定池中分布的鳄鱼的坐标、以及007一次能跳跃的最大距离,你需要告诉他是否有可能逃出生天。

输入格式:

首先第一行给出两个正整数:鳄鱼数量 N(≤100)和007一次能跳跃的最大距离 D。随后 N 行,每行给出一条鳄鱼的 (x,y) 坐标。注意:不会有两条鳄鱼待在同一个点上。

输出格式:

如果007有可能逃脱,就在一行中输出"Yes",否则输出"No"。

输入样例 1:

14 20
25 -15
-25 28
8 49
29 15
-35 -2
5 28
27 -29
-8 -28
-20 -35
-25 -20
-13 29
-30 15
-35 40
12 12

输出样例 1:

Yes

输入样例 2:

4 13
-12 12
12 12
-12 -12
12 -12

输出样例 2:

No

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

思路

用BFS判断能不能走到鳄鱼池旁边即可。

两个点相邻的依据。两个点的距离<=D。

输入时将所有能在池心岛一脚跳过去的点入队。

AC代码

#include<iostream>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
int N, D;
int book[110];
struct Node {int x, y;int i;
};
queue<Node> q;
vector<Node> g;
bool flag = false;
void bfs()
{while (!q.empty()) {Node node = q.front();q.pop();for (int i = 0; i < N; i++) {if (book[i] == 1 || i == node.i) continue;int dx = abs(g[i].x - node.x);int dy = abs(g[i].y - node.y);int dis = dx * dx + dy * dy;if (dis <= D * D) {q.push(g[i]);book[i] = 1;int minedgex = min(abs(g[i].x - 50), abs(g[i].x + 50));int minedgey = min(abs(g[i].y - 50), abs(g[i].y + 50));if (minedgex <= D || minedgey <= D) { flag = true; return; }}}}
}
int main()
{cin >> N >> D;double maxdis = (7.5 + D) * (7.5 + D);//处理输入,先将能从池心岛一步跳往的点入队for (int i = 0; i < N; i++) {int x, y;cin >> x >> y;g.push_back({ x,y,i });if (x * x + y * y <= maxdis) {q.push({ x,y,i });book[i] = 1;//该点距离鳄鱼池左右边界的最短距离int minedgex = min(abs(x - 50), abs(x + 50));//该点距离鳄鱼池上下边界的最短距离int minedgey = min(abs(y - 50), abs(y + 50));if (minedgex <= D || minedgey <= D) { flag = true; }}}if(!flag) bfs();if (flag) cout << "Yes";else cout << "No";
}

//

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/820784.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Springboot+Vue的Java项目-免税商品优选购物商城系统开发实战(附演示视频+源码+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &am…

DC-3渗透测试复现

DC-3渗透测试复现 目的&#xff1a; 获取最高权限以及5个flag 过程&#xff1a; 信息打点-sql注入-反弹shell- pkexec提权&#xff08;CVE-2021-4034&#xff09; 环境&#xff1a; 攻击机&#xff1a;kali(192.168.85.136) 靶机&#xff1a;DC_3(192.168.85.133) 复现…

特斯拉宣布 10%大裁员;刘强东数字人开启直播首秀丨 RTE 开发者日报 Vol.185

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

目标检测——YOLO系列学习(一)YOLOv1

YOLO可以说是单阶段的目标检测方法的集大成之作&#xff0c;必学的经典论文&#xff0c;从准备面试的角度来学习一下yolo系列。 YOLOv1 1.RCNN系列回顾 RCNN系列&#xff0c;无论哪种算法&#xff0c;核心思路都是Region Proposal&#xff08;定位&#xff09; classifier&am…

链表拓展之双向链表

前言 在前面已经总结了单链表&#xff0c;有了单链表的基础会很好理解双链表的实现&#xff0c;忘记了可以跳转——>http://t.csdnimg.cn/GFPk9 接下来就由我带着各位看官来认识今天的主角吧~ 什么是双向链表 在单链表的基础上&#xff0c;它有两个方向的链接&#xff0c;一…

第二期书生浦语大模型训练营第五次笔记

模型部署 模型部署对于任何大模型来说是非常关键的一步。一旦模型经过训练并达到预期的性能指标,就需要将其部署到实际的生产环境中,为最终用户提供服务。但是在部署过程中,大型模型会面临一些独特的挑战。 面临的挑战 大模型在部署方面有一个难题&#xff0c;就是大模型的“大…

fatal: Out of memory, malloc failed

git 切分支&#xff0c;或者clone仓库的时候碰到这个错误&#xff0c;看网上很多配置config文件&#xff0c;都尝试了没效果。 自测了一个可行的方式&#xff1a; 由于本人用的sourcetree 所以解决方式如下&#xff1a; git升级为最新版&#xff0c;选择系统GIt版本&#xf…

加强金融行业关键信息基础设施安全保护,有效防范网络安全风险

当前&#xff0c;随着数字化发展的不断深入&#xff0c;关键信息基础设施作为国家的重要战略资源&#xff0c;面临着国内外严峻的网络安全风险。为了确保国家安全&#xff0c;在国家发展各领域和全过程中&#xff0c;需要将安全发展贯穿始终&#xff0c;筑牢国家安全屏障。金融…

打一把王者的时间,学会web页面测试方法与测试用例编写

一、输入框 1、字符型输入框&#xff1a; &#xff08;1&#xff09;字符型输入框&#xff1a;英文全角、英文半角、数字、空或者空格、特殊字符“~&#xff01;#&#xffe5;%……&*&#xff1f;[]{}”特别要注意单引号和&符号。禁止直接输入特殊字符时&#xff0c;…

【Altium Designer 20 笔记】PCB铺铜过程

PCB铺铜步骤 切换到Keep-Out Layer&#xff08;禁止布线层&#xff09; 使用shifts键切换单层显示 画禁止布线范围&#xff08;防止铺铜过大&#xff09; 切换到需要铺铜的层 选择铺铜网络&#xff0c;通常是地&#xff08;GND&#xff09;或某个电源网络 隐藏覆铜&#xff1a;…

SpringBoot项目接入Nacos注册中心

前置 已经安装好Nacos服务&#xff0c;并且该项目所在服务器可以访问到 可以参考下&#xff1a; windows环境安装Nacos单机版-CSDN博客 Centos7安装Nacos单机版-CSDN博客 1. POM文件引入依赖 注意&#xff0c;父工程已经引入spring cloud依赖管理的情况下不用添加版本号 …

CAN网络管理(网络节点)

什么是CAN的网络节点 网络节点是指连接到CAN总线上的设备或模块,每个网络节点都具有唯一的标识符,称为节点ID,用于在CAN总线上进行通信和识别。 如何判断CAN的网络节点是多少 可以根据DBC来定义查看, 以ADCU为例,域控作为主节点,一般外部的像雷达,camera的数据都是向…

使用 create-vue 脚手架工具创建一个基于 Vite 的项目,并包含加入 Vue Router 等可选项

如果你打算启动一个新项目&#xff0c;你可能会发现使用 create-vue 这个脚手架工具更容易&#xff0c;它能创建一个基于 Vite 的项目&#xff0c;并包含加入 Vue Router 的选项&#xff0c;指令如下&#xff1a; // npm npm create vuelatest// yarn yarn create vue// pnpm …

Postman 环境变量配置初始调用登录脚本赋值Token

效果 新建环境 切换 Environments 标签下 点击上面加号增加环境变量 使用环境变量 使用{{变量名}}引用变量使用 Pre-request Script 全局 一般授权接口都需要再调用接口前&#xff0c;进行登录授权&#xff0c;这里使用了全局的请求前脚本调用。 脚本示例 // 基础地址 var…

Jenkins上面使用pnpm打包

问题 前端也想用Jenkins的CI/CD工作流。 步骤 Jenkins安装NodeJS插件 安装完成&#xff0c;记得重启Jenkins。 全局配置nodejs Jenksinfile pipeline {agent anytools {nodejs "18.15.0"}stages {stage(Check tool version) {steps {sh node -vnpm -vnpm config…

分类损失函数与评估指标

目录 1 评估指标 1.1 准确率 1.2 精确率 1.3 召回率 1.4 F1 score 1.5 ROC曲线 1.6 AUC 目录 1 评估指标 1.1 准确率 1.2 精确率 1.3 召回率 1.4 F1 score 1.5 ROC曲线 1.6 AUC 1.7 PRC曲线的优势 2 损失函数 1. 负对数似然损失 2. 交叉熵损失 3. 指数损失 …

基于SSM的游戏攻略管理系统

游戏攻略管理系统的构建与实现 一、系统概述二、系统架构与技术选型三、系统功能模块四、系统特点五、总结与展望 随着网络游戏的普及和发展&#xff0c;游戏攻略成为玩家们提升游戏技能、了解游戏机制的重要途径。为了更好地满足玩家需求&#xff0c;提高游戏攻略的管理效率和…

OpenHarmony轻量系统开发【7】驱动之I2C显示OLED屏幕

7.1实验效果 Hispark WiFi开发套件又提供一个oled屏幕&#xff0c;但是鸿蒙源码中没有这个屏幕的驱动&#xff0c;我们需要自己去移植。 以下是移植效果&#xff1a; 接口&#xff1a;I2C 使用引脚&#xff1a;HI_IO_NAME_GPIO_13 、 HI_IO_NAME_GPIO_14 7.2代码 这里我直…

供应链金融机器学习建模实战

随着全球贸易的不断发展和供应链的日益复杂化&#xff0c;供应链金融作为一种新型金融工具&#xff0c;正逐渐受到企业和金融机构的关注和重视。供应链金融是指通过金融手段来优化和改进供应链中的资金流动和货物流动&#xff0c;以实现企业间的合作共赢。 供应链金融的核心是将…

大模型微调技术概览解读(chatGLM-6B)

目录 一些比较流行的PEFT方案 Prompt Tuning Prefix Tuning LoRA QLoRA 引用链接 参考文档&#xff1a;通俗解读大模型微调(Fine Tuning) - 知乎 从参数规模的角度&#xff0c;大模型的微调分成两条技术路线&#xff1a; 一条是对全量的参数&#xff0c;进行全量的训练…