P1636 Einstein学画画
题目描述
Einstein 学起了画画。
此人比较懒~~,他希望用最少的笔画画出一张画……
给定一个无向图,包含 n 个顶点(编号 1∼n),m 条边,求最少用多少笔可以画出图中所有的边。
输入格式
第一行两个整数n,m。
接下来 m 行,每行两个数a,b(a≠b),表示 a,b 两点之间有一条边相连。
一条边不会被描述多次。
输出格式
一个数,即问题的答案。
输入输出样例
输入 #1复制
5 5
2 3
2 4
2 5
3 4
4 5
输出 #1复制
1
说明/提示
对于 50% 的数据,n≤50,m≤100。
对于 100% 的数据,1≤n≤1000,1≤m≤10^5。
答案为奇点数/2
#include<bits/stdc++.h>
using namespace std;
int c[1005],n,m,ans;
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
c[a]++;
c[b]++;
}
for(int i=1;i<=n;i++)
{
if(c[i]%2)ans++;
}
if(ans==0)ans=2;
cout<<ans/2;
}
P8654 [蓝桥杯 2017 国 C] 合根植物
题目描述
w 星球的一个种植园,被分成m×n 个小格子(东西方向 m 行,南北方向 n 列)。每个格子里种了一株合根植物。
这种植物有个特点,它的根可能会沿着南北或东西方向伸展,从而与另一个格子的植物合成为一体。
如果我们告诉你哪些小格子间出现了连根现象,你能说出这个园中一共有多少株合根植物吗?
输入格式
第一行,两个整数 m,n,用空格分开,表示格子的行数、列数(1<m,n<1000)。
接下来一行,一个整数 k,表示下面还有 k 行数据 (0<k<10^5)。
接下来 k 行,第行两个整数 a,b,表示编号为 a 的小格子和编号为 b 的小格子合根了。
格子的编号一行一行,从上到下,从左到右编号。
比如:5×4 的小格子,编号:
1 2345 6789 10111213 14151617 181920
输出格式
一行一个整数,表示答案
输入输出样例
输入 #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
说明/提示
样例解释
![](https://i-blog.csdnimg.cn/blog_migrate/ac466435f5342951f26907b17d998e90.png)
时限 1 秒, 256M。蓝桥杯 2017 年第八届国赛
遍历每一个格子,若当前格子未标记,则进行dfs,对所有与这个格子连通的格子(包括这个起始点)进行标记,同时ans+1。
#include<bits/stdc++.h>
using namespace std;
int m,n,num,ans;
struct node
{
int vis;
vector <int> l;
}N[1000005];
void dfs(int s)
{
N[s].vis=1;
for(int i=0;i<N[s].l.size();i++)
{
if(!N[N[s].l[i]].vis)dfs(N[s].l[i]);
}
return;
}
int main()
{
cin>>m>>n;
cin>>num;
for(int i=1;i<=num;i++)
{
int a,b;
cin>>a>>b;
N[a].l.push_back(b);
N[b].l.push_back(a);
}
for(int i=1;i<=n*m;i++)
{
if(N[i].vis)continue;
dfs(i);
ans++;
}
cout<<ans;
}
P3958 [NOIP2017 提高组] 奶酪
题目背景
NOIP2017 提高组 D2T1
题目描述
现有一块大奶酪,它的高度为 h,它的长度和宽度我们可以认为是无限大的,奶酪中间有许多半径相同的球形空洞。我们可以在这块奶酪中建立空间坐标系,在坐标系中,奶酪的下表面为z=0,奶酪的上表面为z=h。
现在,奶酪的下表面有一只小老鼠 Jerry,它知道奶酪中所有空洞的球心所在的坐标。如果两个空洞相切或是相交,则 Jerry 可以从其中一个空洞跑到另一个空洞,特别地,如果一个空洞与下表面相切或是相交,Jerry 则可以从奶酪下表面跑进空洞;如果一个空洞与上表面相切或是相交,Jerry 则可以从空洞跑到奶酪上表面。
位于奶酪下表面的 Jerry 想知道,在不破坏奶酪的情况下,能否利用已有的空洞跑 到奶酪的上表面去?
空间内两点 P1(x1,y1,z1)、P2(x2,y2,z2) 的距离公式如下:
dist(P1,P2)=(x1−x2)^2+(y1−y2)^2+(z1−z2)^2
输入格式
每个输入文件包含多组数据。
第一行,包含一个正整数 T,代表该输入文件中所含的数据组数。
接下来是 T 组数据,每组数据的格式如下: 第一行包含三个正整数 n,h,r,两个数之间以一个空格分开,分别代表奶酪中空洞的数量,奶酪的高度和空洞的半径。
接下来的 n 行,每行包含三个整数x,y,z,两个数之间以一个空格分开,表示空洞球心坐标为 (x,y,z)。
输出格式
T 行,分别对应 T 组数据的答案,如果在第 i 组数据中,Jerry 能从下表面跑到上表面,则输出 Yes,如果不能,则输出 No。
输入输出样例
输入 #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
说明/提示
【输入输出样例 1 说明】
![](https://i-blog.csdnimg.cn/blog_migrate/5f58ebdca2b6996e328cf3d8dfa85e08.png)
第一组数据,由奶酪的剖面图可见:
第一个空洞在 (0,0,0) 与下表面相切;
第二个空洞在 (0,0,4) 与上表面相切;
两个空洞在(0,0,2) 相切。
输出 Yes。
第二组数据,由奶酪的剖面图可见:
两个空洞既不相交也不相切。
输出 No。
第三组数据,由奶酪的剖面图可见:
两个空洞相交,且与上下表面相切或相交。
输出 Yes。
【数据规模与约定】
对于20% 的数据,n=1,1≤h,r≤10^4,坐标的绝对值不超过 10^4。
对于 40% 的数据,1≤n≤8,1≤h,r≤10^4,坐标的绝对值不超过 10^4。
对于 80% 的数据,1≤n≤10^3,1≤h,r≤10^4,坐标的绝对值不超过 10^4。
对于 100% 的数据,1≤n≤1×10^3,1≤h,r≤10^9,T≤20,坐标的绝对值不超过 10^9。
从每一个能碰到底部的球开始进行dfs,若存在通道,则输出Yes,反之输出No。
#include<bits/stdc++.h>
using namespace std;
long long T,n,h,r,ans;
struct ball
{
long long x,y,z,vis;
}b[1005];
double dis(ball a,ball b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}
void dfs(long long s)
{
b[s].vis=1;
if(h-b[s].z<=r)
{
ans=1;
return;
}
for(int i=1;i<=n;i++)
{
if(b[i].vis==0&&dis(b[s],b[i])<=2*r)dfs(i);
}
}
int main()
{
cin>>T;
for(int ii=0;ii<T;ii++)
{
cin>>n>>h>>r;
ans=0;
for(long long i=1;i<=n;i++)
{
b[i].vis=0;
cin>>b[i].x>>b[i].y>>b[i].z;
}
for(long long i=1;i<=n;i++)
{
if(b[i].vis||b[i].z>r)continue;
dfs(i);
if(ans)break;
}
if(ans)cout<<"Yes\n";
else cout<<"No\n";
}
}
P1119 灾后重建
题目背景
B 地区在地震过后,所有村庄都造成了一定的损毁,而这场地震却没对公路造成什么影响。但是在村庄重建好之前,所有与未重建完成的村庄的公路均无法通车。换句话说,只有连接着两个重建完成的村庄的公路才能通车,只能到达重建完成的村庄。
题目描述
给出 B 地区的村庄数 NN,村庄编号从 0 到N−1,和所有 M 条公路的长度,公路是双向的。并给出第 i 个村庄重建完成的时间 ti,你可以认为是同时开始重建并在第 ti 天重建完成,并且在当天即可通车。若 ti 为 0 则说明地震未对此地区造成损坏,一开始就可以通车。之后有 Q 个询问 (x,y,t),对于每个询问你要回答在第 t 天,从村庄 x 到村庄 y 的最短路径长度为多少。如果无法找到从 x 村庄到 y 村庄的路径,经过若干个已重建完成的村庄,或者村庄 x 或村庄 y 在第 t 天仍未重建完成,则需要返回 -1。
输入格式
第一行包含两个正整数N,M,表示了村庄的数目与公路的数量。
第二行包含N个非负整数t0,t1,…,tN−1,表示了每个村庄重建完成的时间,数据保证了t0≤t1≤…≤tN−1。
接下来M行,每行3个非负整数i,j,w,w为不超过10000的正整数,表示了有一条连接村庄i与村庄j的道路,长度为w,保证i≠j,且对于任意一对村庄只会存在一条道路。
接下来一行也就是M+3行包含一个正整数Q,表示Q个询问。
接下来Q行,每行3个非负整数x,y,t,询问在第t天,从村庄x到村庄y的最短路径长度为多少,数据保证了t是不下降的。
输出格式
共Q行,对每一个询问(x,y,t)输出对应的答案,即在第t天,从村庄x到村庄y的最短路径长度为多少。如果在第t天无法找到从x村庄到y村庄的路径,经过若干个已重建完成的村庄,或者村庄x或村庄y在第t天仍未修复完成,则输出−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%的数据,有N≤50;
对于30%的数据,有ti=0,其中有20%的数据有ti=0且N>50;
对于50%的数据,有Q≤100;
对于100%的数据,有N≤200,M≤N×(N−1)/2,Q≤50000,所有输入数据涉及整数均不超过100000。
在每一个村庄重建完成后,更新通过该村庄的最短路径。
#include<bits/stdc++.h>
using namespace std;
const int inf=1e9;
int n,m,L[205][205],t[205],Q,now=0;
inline void update(int k)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(L[i][j]>L[i][k]+L[j][k])L[i][j]=L[j][i]=L[i][k]+L[j][k];
}
}
return ;
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)cin>>t[i];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
L[i][j]=(i==j?0:inf);
}
}
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
L[a][b]=L[b][a]=c;
}
cin>>Q;
for(int i=1;i<=Q;i++)
{
int a,b,c;
cin>>a>>b>>c;
while(t[now]<=c&&now<n)
{
update(now);
now++;
}
if(t[a]>c||t[b]>c||L[a][b]==inf)cout<<"-1\n";
else cout<<L[a][b]<<endl;
}
}
P2504 [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复制
4
1 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 修正数据
Kruskal
#include<bits/stdc++.h>
using namespace std;
int n,m,M[505],x[1005],y[1005],fa[1005],N=0,ans;
double Max;
struct lll
{
int s,d;
double len;
}L[1000005];
double dis(int s,int d)
{
return sqrt((x[s]-x[d])*(x[s]-x[d])+(y[s]-y[d])*(y[s]-y[d]));
}
bool cmp(lll a,lll b)
{
return a.len<b.len;
}
int find(int s)
{
if(fa[s]!=s)return find(fa[s]);
else return s;
}
int main()
{
cin>>m;
for(int i=1;i<=m;i++)cin>>M[i];
cin>>n;
for(int i=1;i<=n;i++)cin>>x[i]>>y[i];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)continue;
N++;
L[N].s=i;
L[N].d=j;
L[N].len=dis(i,j);
}
}
for(int i=1;i<=n;i++)fa[i]=i;
sort(L+1,L+N+1,cmp);
int cnt=n;
for(int i=1;i<=N;i++)
{
if(cnt==1)break;
int f1=find(L[i].s),f2=find(L[i].d);
if(f1!=f2)
{
fa[f1]=f2;
cnt--;
Max=max(Max,L[i].len);
}
}
for(int i=1;i<=m;i++)
{
if(M[i]>=Max)ans++;
}
cout<<ans;
}