7-143 Partial School Ranking
题目
给定每个人的编号,这个人已知的 与他同组的人数,与他同组的人们的编号,这个人的得分。
你需要把所有人分好组,无论是直接或间接给定的关系都算作一组。
输出组数后,把这些组按给定的顺序输出要求的信息。
顺序:按总分数降序,相同则按组内人数升序,还相同按组内最小编号的人的编号升序。
输出内容:编号 人数 总分数
解题报告
“加边,加边,加边,然后并查集查询。”
可以概括成这一句 经典话语。
你需要按照给定的关系把那些人用并查集维护到同一组即可,最后扫一遍统计信息即可。
注意可能会有一些人,只出现在别人的关系中(用原题意的话就是:“只出现在别人照片里”)但是本人的信息未给出的存在。
因为编号的范围很小所以比较好写的写法是枚举编号。
Code
#include <stdio.h>
#include <algorithm>
#define LL long long
using namespace std;
const int Rea=1e5+3;
int ps[4]={1000,100,10,0};
struct Rin
{
char c;
inline char gc()
{
static char rea[Rea];
static char *head,*tail;
return head==tail&&(tail=(head=rea)+fread(rea,1,Rea,stdin),head==tail)?EOF:*head++;
}
inline Rin&operator >>(int &x)
{
x=0;
bool tag=false;
for(c=gc();c>'9'||c<'0';c=gc())if(c=='-'){c=gc();tag=true;break;}
for(;c>='0'&&c<='9';c=gc())x=(x<<1)+(x<<3)+(c^'0');
if(tag)x=-x;
return *this;
}
inline Rin&operator <<(int x){for(int j=0;j<4;j++)if(x<ps[j])putchar(48);printf("%d",x);return *this;}
}rin;
const int N=1e3+3;
const int M=1e5+3;
int f[M];
inline int find(int x){return f[x]==x?x:(f[x]=find(f[x]));}
inline void add(int x,int y){if(find(x)!=find(y))f[find(x)]=find(y);return;}
int n,m;
int num[N];
int pri[M];
int cut[M];
int sum[M];
bool tag[M];
int d[N];
int tail;
inline bool myru_d(int x,int y){return sum[x]==sum[y]?(cut[x]==cut[y]?pri[x]<pri[y]:cut[x]<cut[y]):sum[x]>sum[y];}
int main()
{
rin>>n;
for(int i=0;i<M;i++)f[i]=i;
for(int i=1;i<=n;i++)
{
rin>>num[i]>>m;pri[num[i]]=num[i];tag[num[i]]=true;cut[num[i]]=1;
for(int j=1,x;j<=m;j++)rin>>x,add(x,num[i]),tag[x]=true;
rin>>sum[num[i]];
}
for(int i=0;i<M;i++)if(tag[i]&&find(i)!=i)sum[find(i)]+=sum[i],cut[find(i)]++,pri[find(i)]=min(pri[find(i)],i);
for(int i=0;i<M;i++)if(tag[i]&&find(i)==i)d[++tail]=i;
sort(d+1,d+tail+1,myru_d);
printf("%d\n",tail);
for(int i=1;i<=tail;i++){rin<<pri[d[i]];printf(" %d %lld\n",cut[d[i]],sum[d[i]]);}
return 0;
}
\[\texttt{El Psy Congroo}
\]
$$\texttt{Dirty Deeds Done Dirt Cheap}$$

浙公网安备 33010602011771号