week10
创始人
2024-05-09 06:09:30

T1 Einstein学画画

题目描述

Einstein 学起了画画。

此人比较懒~~,他希望用最少的笔画画出一张画……

给定一个无向图,包含 nnn 个顶点(编号 1∼n1 \sim n1∼n),mmm 条边,求最少用多少笔可以画出图中所有的边。

输入格式

第一行两个整数 n,mn, mn,m。

接下来 mmm 行,每行两个数 a,ba, ba,b(a≠ba \ne ba=b),表示 a,ba, ba,b 两点之间有一条边相连。

一条边不会被描述多次。

输出格式

一个数,即问题的答案。

样例 #1

样例输入 #1

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

样例输出 #1

1

提示

对于 50%50 \%50% 的数据,n≤50n \le 50n≤50,m≤100m \le 100m≤100。

对于 100%100\%100% 的数据,1≤n≤10001 \le n \le 10001≤n≤1000,1≤m≤1051 \le m \le {10}^51≤m≤105。

思路:如果一个图中的奇数点为0或≥2且不被2整除的图则这个图可以被一笔画,否则这个图可以被奇数点个数 / 2 笔画出。

代码:

#include 
using namespace std;
int arr[100005] = {}, n, m, num = 0;
int main()
{cin >> n >> m;for (int i = 1;i <= m;i++){int a, b;cin >> a >> b;arr[a]++;arr[b]++;}for (int i = 1;i <= m;i++){if (arr[i] % 2 == 1)          //有奇数条路经过这个点 num++;}if (num != 0)cout << num / 2 << endl;elsecout << "1" << endl;return 0;
}

T2 [蓝桥杯 2017 国 C] 合根植物

题目描述

w 星球的一个种植园,被分成 m×nm \times nm×n 个小格子(东西方向 mmm 行,南北方向 nnn 列)。每个格子里种了一株合根植物。

这种植物有个特点,它的根可能会沿着南北或东西方向伸展,从而与另一个格子的植物合成为一体。

如果我们告诉你哪些小格子间出现了连根现象,你能说出这个园中一共有多少株合根植物吗?

输入格式

第一行,两个整数 mmm,nnn,用空格分开,表示格子的行数、列数(1

接下来一行,一个整数 kkk,表示下面还有 kkk 行数据 (0

接下来 kkk 行,第行两个整数 aaa,bbb,表示编号为 aaa 的小格子和编号为 bbb 的小格子合根了。

格子的编号一行一行,从上到下,从左到右编号。

比如:5×45 \times 45×4 的小格子,编号:

1  2  3  4
5  6  7  8
9  10 11 12
13 14 15 16
17 18 19 20

输出格式

一行一个整数,表示答案

样例 #1

样例输入 #1

5 4
16
2 3
1 5
5 9
4 8
7 8
9 10
10 11
11 12
10 14
12 16
14 18
17 18
15 19
19 20
9 13
13 17

样例输出 #1

5

提示

样例解释

时限 1 秒, 256M。蓝桥杯 2017 年第八届国赛

思路:通过对已经访问过的点标记算作一个集合,已被标记的不能被访问,集合的个数就是合根植物数

代码:

#include
using namespace std;
bool vis[1000005] = { false };
vector  dp[1000000];
int arr[1000005] = {}, m, n;void dfs(int now)
{int i, j;vis[now] = true;             //已经走过for (i = 0;i < arr[now];i++){j = dp[now][i];if (vis[j] == false){vis[j] = true;       //已经遍历dfs(j);}}
}int main()
{long int num = 0;int a, b, now, k;cin >> m >> n >> k;for (int i = 1;i <= k;i++){cin >> a >> b;dp[a].push_back(b);dp[b].push_back(a);arr[a]++;arr[b]++;}for (int i = 1;i <= m;i++){for (int j = 1;j <= n;j++){now = (i - 1) * n + j;if (vis[now] == true)continue;else{dfs(now);num++;}}}cout << num;return 0;
}

T3[NOIP2017 提高组] 奶酪

题目背景

NOIP2017 提高组 D2T1

题目描述

现有一块大奶酪,它的高度为 hhh,它的长度和宽度我们可以认为是无限大的,奶酪中间有许多半径相同的球形空洞。我们可以在这块奶酪中建立空间坐标系,在坐标系中,奶酪的下表面为 z=0z = 0z=0,奶酪的上表面为 z=hz = hz=h。

现在,奶酪的下表面有一只小老鼠 Jerry,它知道奶酪中所有空洞的球心所在的坐标。如果两个空洞相切或是相交,则 Jerry 可以从其中一个空洞跑到另一个空洞,特别地,如果一个空洞与下表面相切或是相交,Jerry 则可以从奶酪下表面跑进空洞;如果一个空洞与上表面相切或是相交,Jerry 则可以从空洞跑到奶酪上表面。

位于奶酪下表面的 Jerry 想知道,在不破坏奶酪的情况下,能否利用已有的空洞跑 到奶酪的上表面去?

空间内两点 P1(x1,y1,z1)P_1(x_1,y_1,z_1)P1​(x1​,y1​,z1​)、P2(x2,y2,z2)P2(x_2,y_2,z_2)P2(x2​,y2​,z2​) 的距离公式如下:

dist(P1,P2)=(x1−x2)2+(y1−y2)2+(z1−z2)2\mathrm{dist}(P_1,P_2)=\sqrt{(x_1-x_2)^2+(y_1-y_2)^2+(z_1-z_2)^2}dist(P1​,P2​)=(x1​−x2​)2+(y1​−y2​)2+(z1​−z2​)2

输入格式

每个输入文件包含多组数据。

第一行,包含一个正整数 TTT,代表该输入文件中所含的数据组数。

接下来是 TTT 组数据,每组数据的格式如下: 第一行包含三个正整数 n,h,rn,h,rn,h,r,两个数之间以一个空格分开,分别代表奶酪中空洞的数量,奶酪的高度和空洞的半径。

接下来的 nnn 行,每行包含三个整数 x,y,zx,y,zx,y,z,两个数之间以一个空格分开,表示空洞球心坐标为 (x,y,z)(x,y,z)(x,y,z)。

输出格式

TTT 行,分别对应 TTT 组数据的答案,如果在第 iii 组数据中,Jerry 能从下表面跑到上表面,则输出 Yes,如果不能,则输出 No

样例 #1

样例输入 #1

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

样例输出 #1

Yes
No
Yes

提示

【输入输出样例 111 说明】

第一组数据,由奶酪的剖面图可见:

第一个空洞在 (0,0,0)(0,0,0)(0,0,0) 与下表面相切;

第二个空洞在 (0,0,4)(0,0,4)(0,0,4) 与上表面相切;

两个空洞在 (0,0,2)(0,0,2)(0,0,2) 相切。

输出 Yes

第二组数据,由奶酪的剖面图可见:

两个空洞既不相交也不相切。

输出 No

第三组数据,由奶酪的剖面图可见:

两个空洞相交,且与上下表面相切或相交。

输出 Yes

【数据规模与约定】

对于 20%20\%20% 的数据,n=1n = 1n=1,1≤h1 \le h1≤h,r≤104r \le 10^4r≤104,坐标的绝对值不超过 10410^4104。

对于 40%40\%40% 的数据,1≤n≤81 \le n \le 81≤n≤8,1≤h1 \le h1≤h,r≤104r \le 10^4r≤104,坐标的绝对值不超过 10410^4104。

对于 80%80\%80% 的数据,1≤n≤1031 \le n \le 10^31≤n≤103,1≤h,r≤1041 \le h , r \le 10^41≤h,r≤104,坐标的绝对值不超过 10410^4104。

对于 100%100\%100% 的数据,1≤n≤1×1031 \le n \le 1\times 10^31≤n≤1×103,1≤h,r≤1091 \le h , r \le 10^91≤h,r≤109,T≤20T \le 20T≤20,坐标的绝对值不超过 10910^9109。

思路:判两个洞球心的距离是否<=2∗r来判断相交,如果相交的话就将这两个洞合并。而判断是否相通,就是看球位置是否<=0∣∣>=h

代码:

#include
using namespace std;
#define num Get()
int T;
long long n, h, r;
int nex[1000005] = {}, tnx[1000005] = {}, head[1005] = {}, ent = 0;
bool vis[1005] = { false };
struct node
{double x, y, z;
}p[1005];
int Get()
{char ch;int f = 1;long long res = 0;while ((ch = getchar()) < '0' || ch > '9')if (ch == '-')f = -1;while (ch >= '0' && ch <= '9'){res = (res * (2 ^ 3) + res / (2 ^ 1)) + ch - '0';ch = getchar();}return f * res;
}void Cal(int x, int y)
{nex[++ent] = head[x];head[x] = ent;tnx[ent] = y;
}bool bfs()
{memset(vis, false, sizeof(vis));queue q;q.push(0);while (!q.empty()){int u = q.front();q.pop();for (int x = head[u];x != 0;x = nex[x]){int v = tnx[x];if (v == n + 1)return true;if (!vis[v]){q.push(v);vis[v] = true;}}}return 0;
}
int main()
{T = num;int i, j, k;while (T--){ent = 0;memset(head, 0, sizeof(head));n = num;h = num;r = num;for (i = 1;i <= n;++i){p[i].x = num;p[i].y = num;p[i].z = num;if (p[i].z - r <= 0){Cal(0, i);Cal(i, 0);}if (p[i].z + r >= h){Cal(n + 1, i);Cal(i, n + 1);}}for (i = 1;i < n;++i)for (j = i + 1;j <= n;++j){double dis = sqrt((p[i].x - p[j].x) * (p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y) + (p[i].z - p[j].z) * (p[i].z - p[j].z));;if (dis <= 2 * r){Cal(i, j);Cal(j, i);}}if (bfs()==true)cout << "Yes" << endl;elsecout << "No" << endl;}return 0;
}

T4灾后重建

题目背景

B 地区在地震过后,所有村庄都造成了一定的损毁,而这场地震却没对公路造成什么影响。但是在村庄重建好之前,所有与未重建完成的村庄的公路均无法通车。换句话说,只有连接着两个重建完成的村庄的公路才能通车,只能到达重建完成的村庄。

题目描述

给出 B 地区的村庄数 NNN,村庄编号从 000 到 N−1N-1N−1,和所有 MMM 条公路的长度,公路是双向的。并给出第 iii 个村庄重建完成的时间 tit_iti​,你可以认为是同时开始重建并在第 tit_iti​ 天重建完成,并且在当天即可通车。若 tit_iti​ 为 000 则说明地震未对此地区造成损坏,一开始就可以通车。之后有 QQQ 个询问 (x,y,t)(x,y,t)(x,y,t),对于每个询问你要回答在第 ttt 天,从村庄 xxx 到村庄 yyy 的最短路径长度为多少。如果无法找到从 xxx 村庄到 yyy 村庄的路径,经过若干个已重建完成的村庄,或者村庄 xxx 或村庄 yyy 在第 ttt 天仍未重建完成,则需要返回 -1

输入格式

第一行包含两个正整数N,MN,MN,M,表示了村庄的数目与公路的数量。

第二行包含NNN个非负整数t0,t1,…,tN−1t_0, t_1,…, t_{N-1}t0​,t1​,…,tN−1​,表示了每个村庄重建完成的时间,数据保证了t0≤t1≤…≤tN−1t_0 ≤ t_1 ≤ … ≤ t_{N-1}t0​≤t1​≤…≤tN−1​。

接下来MMM行,每行333个非负整数i,j,wi, j, wi,j,w,www为不超过100001000010000的正整数,表示了有一条连接村庄iii与村庄jjj的道路,长度为www,保证i≠ji≠ji=j,且对于任意一对村庄只会存在一条道路。

接下来一行也就是M+3M+3M+3行包含一个正整数QQQ,表示QQQ个询问。

接下来QQQ行,每行333个非负整数x,y,tx, y, tx,y,t,询问在第ttt天,从村庄xxx到村庄yyy的最短路径长度为多少,数据保证了ttt是不下降的。

输出格式

共QQQ行,对每一个询问(x,y,t)(x, y, t)(x,y,t)输出对应的答案,即在第ttt天,从村庄xxx到村庄yyy的最短路径长度为多少。如果在第t天无法找到从xxx村庄到yyy村庄的路径,经过若干个已重建完成的村庄,或者村庄x或村庄yyy在第ttt天仍未修复完成,则输出−1-1−1。

样例 #1

样例输入 #1

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

样例输出 #1

-1
-1
5
4

提示

对于30%30\%30%的数据,有N≤50N≤50N≤50;

对于30%30\%30%的数据,有ti=0t_i= 0ti​=0,其中有20%20\%20%的数据有ti=0t_i = 0ti​=0且N>50N>50N>50;

对于50%50\%50%的数据,有Q≤100Q≤100Q≤100;

对于100%100\%100%的数据,有N≤200N≤200N≤200,M≤N×(N−1)/2M≤N \times (N-1)/2M≤N×(N−1)/2,Q≤50000Q≤50000Q≤50000,所有输入数据涉及整数均不超过100000100000100000。

思路:最短路的题目中,如果节点数量非常的少,那就是在提示我们使用floyd,本题主要是用floyd对每两个结点间距离进行更新来解题

代码:

#include
using namespace std;
const int INF = 999999999;
int t[1005] = {}, N, now, K, res[1005][1005] = {};int main()
{cin >> N >> now;fill(res[0], res[0] + 1005 * 1005, INF);for (int i = 0; i < N; i++){cin >> t[i];res[i][i] = 0;}for (int i = 0; i < now; i++){int u, v, w;cin >> u >> v >> w;res[u][v] = w;res[v][u] = w;}cin >> K;int now = 0;for (int i = 0; i < K; i++){int x, y, z;cin >> x >> y >> z;for (;t[now] <= z && now < N; now++){                                //floydfor (int i = 0; i < N; i++){for (int j = 0; j < N; j++){if (res[i][now] != INF && res[now][j] != INF && res[i][now] + res[now][j] < res[i][j]){res[j][i] = res[i][j] = res[i][now] + res[now][j];}}}}if (t[x] > z || t[y] > z || res[x][y] == INF)cout << "-1" << endl;elsecout << res[x][y] << endl;}return 0;
}

T5 [HAOI2006]聪明的猴子

题目描述

在一个热带雨林中生存着一群猴子,它们以树上的果子为生。昨天下了一场大雨,现在雨过天晴,但整个雨林的地表还是被大水淹没着,部分植物的树冠露在水面上。猴子不会游泳,但跳跃能力比较强,它们仍然可以在露出水面的不同树冠上来回穿梭,以找到喜欢吃的果实。

现在,在这个地区露出水面的有N棵树,假设每棵树本身的直径都很小,可以忽略不计。我们在这块区域上建立直角坐标系,则每一棵树的位置由其所对应的坐标表示(任意两棵树的坐标都不相同)。

在这个地区住着的猴子有M个,下雨时,它们都躲到了茂密高大的树冠中,没有被大水冲走。由于各个猴子的年龄不同、身体素质不同,它们跳跃的能力不同。有的猴子跳跃的距离比较远(当然也可以跳到较近的树上),而有些猴子跳跃的距离就比较近。这些猴子非常聪明,它们通过目测就可以准确地判断出自己能否跳到对面的树上。

【问题】现已知猴子的数量及每一个猴子的最大跳跃距离,还知道露出水面的每一棵树的坐标,你的任务是统计有多少个猴子可以在这个地区露出水面的所有树冠上觅食。

输入格式

输入文件monkey.in包括:

第1行为一个整数,表示猴子的个数M(2<=M<=500);

第2行为M个整数,依次表示猴子的最大跳跃距离(每个整数值在1–1000之间);

第3行为一个整数表示树的总棵数N(2<=N<=1000);

第4行至第N+3行为N棵树的坐标(横纵坐标均为整数,范围为:-1000–1000)。

(同一行的整数间用空格分开)

输出格式

输出文件monkey.out包括一个整数,表示可以在这个地区的所有树冠上觅食的猴子数。

样例 #1

样例输入 #1

41 2 3 4
6
0 0
1 0
1 2
-1 -1
-2 0
2 2

样例输出 #1

3

提示

【数据规模】

对于40%的数据,保证有2<=N <=100,1<=M<=100

对于全部的数据,保证有2<=N <= 1000,1<=M=500

感谢@charlie003 修正数据

思路:本题为最小生成树问题,先求出原图的最小生成树,猴子如果想自由地觅食必须满足猴子的跳跃距离一定>=原图最小生成树的最大边,通过这种思路解决该问题

代码:

#include
using namespace std;
double num;
int arr[1005] = {}, rex[1005] = {}, rey[1005] = {}, fd[1005] = {}, m, n, ind, k, ans;
struct node
{int x, y;double v;
}nod[1000005];int Now(int p)
{if (fd[p] != p)fd[p] = Now(fd[p]);return fd[p];
}bool cmp(const node& x, const node& y)
{return x.v < y.v;
}
int main()
{cin >> m;for (int i = 1;i <= m;i++)cin >> arr[i];cin >> n;for (int i = 1;i <= n;i++)cin >> rex[i] >> rey[i];for (int i = 1;i <= n;i++)for (int j = 1;j <= n;j++){nod[++ind].x = i;nod[ind].y = j;nod[ind].v = sqrt((rex[i] - rex[j]) * (rex[i] - rex[j]) + (rey[i] - rey[j]) * (rey[i] - rey[j]));}for (int i = 1;i <= n;i++)fd[i] = i;sort(nod + 1, nod + n * n + 1, cmp);            //排序for (int i = 1;i <= n * n;i++){if (Now(nod[i].x) != Now(nod[i].y)){int fx = Now(nod[i].x);int fy = Now(nod[i].y);if (fx != fy)fd[fx] = fy;num = max(num, nod[i].v);k++;}if (k == n - 1)break;}for (int i = 1;i <= m;i++){if (arr[i] >= num)ans++;}cout << ans << endl;return 0;
}

相关内容

热门资讯

脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...