团体天梯练习 L2-024 部落
Posted MAKISE004
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了团体天梯练习 L2-024 部落相关的知识,希望对你有一定的参考价值。
L2-024 部落
在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不同的朋友圈。我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查任意两个人是否属于同一个部落。
输入格式:
输入在第一行给出一个正整数 \\(N\\) ( \\(≤10^4\\) ),是已知小圈子的个数。随后 \\(N\\) 行,每行按下列格式给出一个小圈子里的人:
\\(K\\) \\(P[1]\\) \\(P[2]\\) ⋯ \\(P[K]\\)
其中 \\(K\\) 是小圈子里的人数, \\(P[i]\\)( \\(i=1,⋯,K\\) )是小圈子里每个人的编号。这里所有人的编号从 \\(1\\) 开始连续编号,最大编号不会超过 \\(10^4\\) 。
之后一行给出一个非负整数 \\(Q\\) ( \\(≤10^4\\) ),是查询次数。随后 \\(Q\\) 行,每行给出一对被查询的人的编号。
输出格式:
首先在一行中输出这个社区的总人数、以及互不相交的部落的个数。随后对每一次查询,如果他们属于同一个部落,则在一行中输出 \\(Y\\) ,否则输出 \\(N\\) 。
输入样例:
4
3 10 1 2
2 3 4
4 1 5 7 8
3 9 6 4
2
10 5
3 7
输出样例:
10 2
Y
N
解题思路
很明显的并查集模板题。题中给出的是每个人关联的所有其他人的编号,不过编号是连续的,所以记录一下最大编号就行了(或者定义一个数组记录这个数字是否存在与集合中)。
/* 一切都是命运石之门的选择 El Psy Kongroo */
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<double, double> pdd;
typedef pair<string, int> psi;
typedef __int128 int128;
#define PI acos(-1.0)
#define x first
#define y second
//int dx[4] = 1, -1, 0, 0;
//int dy[4] = 0, 0, 1, -1;
const int inf = 0x3f3f3f3f, mod = 1e9 + 7;
const int N = 1e4 + 10;
int n, m, k, fa[N], s[N];
//m记录最大编号
void init()
for(int i = 1; i < N; i ++ ) fa[i] = i, s[i] = 1;
int find(int x)
return fa[x] == x ? x : (fa[x] = find(fa[x]));
void Union(int x, int y)
int fx = find(x), fy = find(y);
if(fx == fy) return;
fa[fx] = fy;
s[fy] += s[fx];
int main()
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
init();
while(n -- )
cin >> k;
int a; cin >> a;
m = max(m, a);
k -- ;
while(k -- )
int b; cin >> b;
Union(a, b);
m = max(m, b);
int cnt = 0, sum = 0;
for(int i = 1; i <= m; i ++ )
if(fa[i] == i) cnt ++ , sum += s[i];
cout << sum << \' \' << cnt << endl;
int q; cin >> q;
while(q -- )
int a, b; cin >> a >> b;
int fx = find(a), fy = find(b);
if(fx == fy) cout << "Y" << endl;
else cout << "N" << endl;
return 0;
一切都是命运石之门的选择,本文章来源于博客园,作者:Amαdeus,出处:https://www.cnblogs.com/MAKISE004/p/17331741.html,未经允许严禁转载
团体程序设计天梯赛-练习集
L2-001 紧急救援 (25 分)
知识点:最短路dij
#include<bits/stdc++.h>
#define debug(x,y) printf("%s = %d\\n",x,y);
typedef long long ll;
using namespace std;
inline int read()
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')if(ch=='-')w=-1;ch=getchar();
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
return s*w;
const int INF=0x3f3f3f;
const int maxn=1000;
int a[maxn];
int edge[maxn][maxn];
int n,m,s,d;
int dis[maxn];
int vis[maxn];
int cnt[maxn];
int num_a[maxn];//最短路上的最大救援队
int pathnum[maxn];//最短路的数量
int path[maxn];
void dij()
pathnum[s]=1;
dis[s]=0;
vis[s]=1;
num_a[s]=a[s];
for(int i=0;i<n;i++)
dis[i]=edge[s][i];
if(edge[s][i]<=INF&&i!=s)
path[i]=s;
num_a[i]=num_a[s]+a[i];
pathnum[i]=1;
for(int i=1;i<n;i++)
int now=0;
int minn=INF;
for(int j=0;j<n;j++)
if(vis[j]==0&&dis[j]<minn)
now=j;
minn=dis[j];
vis[now]=1;
for(int j=0;j<n;j++)
if(!vis[j])
if(dis[j]==edge[now][j]+minn)
pathnum[j]+=pathnum[now];
if(num_a[j]<num_a[now]+a[j])
num_a[j]=num_a[now]+a[j];
path[j]=now;
else if(dis[j]>edge[now][j]+minn)
dis[j]=edge[now][j]+minn;
num_a[j]=num_a[now]+a[j];
pathnum[j]=pathnum[now];
path[j]=now;
void print(int now)
if(now==s)
return ;
print(path[now]);
cout<<" "<<now;
int main()
// memset(edge,0x3f3f3f,sizeof(edge));
cin>>n>>m>>s>>d;
for(int i=0;i<n;i++)
dis[i]=INF;
for(int j=0;j<n;j++)
edge[i][j]=edge[j][i]=INF;
for(int i=0;i<n;i++)cin>>a[i];
for(int i=1;i<=m;i++)
int u,v,w;
cin>>u>>v>>w;
edge[u][v]=w;
edge[v][u]=w;
dij();
cout<<pathnum[d]<<" "<<num_a[d]<<endl;
cout<<s;
print(d);
L2-002 链表去重 (25 分)
知识点:模拟链表
#include<bits/stdc++.h>
#define debug(x,y) printf("%s = %d\\n",x,y);
typedef long long ll;
using namespace std;
inline int read()
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')if(ch=='-')w=-1;ch=getchar();
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
return s*w;
const int maxn=2e5+9;
struct node
int add;
int val,next;
link[maxn],b[maxn];
int vis[maxn];
int tot=0;
int main()
int beg,n;
cin>>beg>>n;
for(int i=1;i<=n;i++)
int add,val,nex;
cin>>add>>val>>nex;
link[add].val=val;
link[add].next=nex;
int now=beg;
// printf("----\\n");
while(1)
// printf("now=%d\\n",now);
if(now==-1)
break;
if(vis[abs(link[now].val)]==0)
if(now!=beg)
printf("%05d\\n",now);
vis[abs(link[now].val)]=1;
printf("%05d %d ",now,link[now].val);
// cout<<now<<" "<<link[now].val<<" "<<link[now].next<<endl;
now=link[now].next;
else
b[++tot].next=link[now].next;
b[tot].add=now;
b[tot].val=link[now].val;
now=link[now].next;
printf("-1\\n");
if(tot)
printf("%05d %d ",b[1].add,b[1].val);
for(int i=2;i<=tot;i++)
printf("%05d\\n%05d %d ",b[i].add,b[i].add,b[i].val);
printf("-1\\n");
L2-003 月饼 (25 分)
知识点:贪心
注意要将种类数和需求数都开成double,不然会被卡一个点
#include<bits/stdc++.h>
#define debug(x,y) printf("%s = %d\\n",x,y);
typedef long long ll;
using namespace std;
inline int read()
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')if(ch=='-')w=-1;ch=getchar();
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
return s*w;
const int maxn=2000;
//int num[maxn];
//int val[maxn];
struct node
double num,val;
double ave;
a[maxn];
bool cmp(node a,node b)
return a.val*b.num>b.val*a.num;
int main()
int n,d;
cin>>n>>d;
for(int i=1;i<=n;i++)cin>>a[i].num;
for(int i=1;i<=n;i++)cin>>a[i].val;
for(int i=1;i<=n;i++)a[i].ave=1.0*a[i].val/a[i].num;
sort(a+1,a+1+n,cmp);
double sum=0;
for(int i=1;i<=n;i++)
// cout<<a[i].ave<<endl;
if(d>=a[i].num)
d-=a[i].num;
sum+=a[i].val;
else
sum+=d*a[i].ave;
break;
printf("%.2f\\n",sum);
L2-004 这是二叉搜索树吗? (25 分)
知识点:考察了前序遍历和后序遍历的应用
#include<bits/stdc++.h>
#define debug(x,y) printf("%s = %d\\n",x,y);
typedef long long ll;
using namespace std;
inline int read()
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')if(ch=='-')w=-1;ch=getchar();
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
return s*w;
const int maxn=2000;
int pos[maxn];
int iff=0;
vector<int>post;
void getpos(int l,int r)
if(l>r)return ;
int tl=l+1,tr=r;
if(!iff)//正常的二叉搜索树
while(tl<=r&&pos[tl]<pos[l])tl++;//找到第一个大的
while(tr>l&&pos[tr]>=pos[l])tr--; //找到第一个小的
else //镜像的
while(tl<=r&&pos[tl]>=pos[l])tl++;
while(tr>l&&pos[tr]<pos[l])tr--;
if(tl!=tr+1)return ;
getpos(l+1,tr);
getpos(tl,r);
// cout<<pos[l]<<endl;
post.push_back(pos[l]);
int main()
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>pos[i];
getpos(1,n);
if(post.size()!=n)
iff=1;
post.clear();
getpos(1,n);
if(post.size()!=n)
cout<<"NO"<<endl;
return 0;
cout<<"YES"<<endl;
for(int i=0;i<n;i++)
if(i==0)
printf("%d",post[i]);
else printf(" %d",post[i]);
return 0;
L2-005 集合相似度 (25 分)
知识点:考察对set的应用情况
#include<bits/stdc++.h>
#define debug(x,y) printf("%s = %d\\n",x,y);
typedef long long ll;
using namespace std;
inline int read()
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')if(ch=='-')w=-1;ch=getchar()以上是关于团体天梯练习 L2-024 部落的主要内容,如果未能解决你的问题,请参考以下文章