珍珠Bead 题解

题解 珍珠(Bead)

题目描述

n 颗形状和大小都一致的珍珠,它们的重量都不相同。 n 为整数,所有的珍珠从 1n 编号。你的任务是发现哪颗珍珠的重量刚好处于中间,即在所有珍珠的重量中,该珍珠的重量列 n+12 位。下面给出将一对珍珠进行比较的办法:

给你一架天平用来比较珍珠的重量,我们珂以比出两个珍珠哪个更重一些,在作出一系列的比较后,我们珂以将某些肯定不具备中间重量的珍珠拿走。

例如,下列给出对 5 颗珍珠进行四次比较的情况:

(1)珍珠 2 比珍珠 1

(2)珍珠 4 比珍珠 3

(3)珍珠 5 比珍珠 1

(4)珍珠 4 比珍珠 2

根据以上结果,虽然我们不能精确地找出哪个珍珠具有中间重量,但我们珂以肯定珍珠 1 和珍珠 4 不珂能具有中间重量,因为珍珠 245 比珍珠 1 重,而珍珠 123 比珍珠 4 轻,所以我们珂以移走这两颗珍珠。

写一个程序统计出共有多少颗珍珠肯定不会是中间重量。

输入

第一行:包含两个用空格隔开的整数 NM ,其中 1N99 ,且 N 为奇数, M 表示对珍珠进行的比较次数

接下来 M 行每行包括两个用空格隔开的整数 xy ,表示珍珠 x 比珍珠 y 重,两个数之间用空格隔开

输出

一行包括一个整数,表示不珂能是中间重量的珍珠的总数。

样例

样例输入
5 4
2 1
4 3
5 1
4 2
样例输出
2

解题思路

一点模拟

首先看到大小关系,想到差分约束

但是差分约束是用来求解方程的,对于这道题显然不太对

不过没关系,我们珂以用差分约束的思路来做这道题

也就是把大小关系转化为图

首先我们按照题目给出的样例模拟一下:

图

按照 ab 就建立 ab 的规律,建立一张图如上

观察图像我们珂以发现一个有趣的地方:

如果 ab 成立,也就是说点 a 能到达 b ,那么一定有 ab

这不是废话吗

两条证明

1、在一个有限递增数列 an(n=2k+1,kN) 中,如果存在一个数 ai ,数列中大于 ai 的数不少于 n+12 个,那么 ai 一定不处于这个数列的第 n+12

证明:

即得易见平凡,仿照上例显然。留作习题答案略,读者自证不难。

2、在一张图中使用 floyd 算法求出最短路后得到最短路邻接矩阵 d[501][501] ,如果 d[i][j]<+ ,那么 ij 成立

证明:

反之亦然同理,推论自然成立。略去过程Q. E. D,由上珂知证毕。

其实这两条命题应该算公理

三段核心代码

1、读入转图

int n,m,d1,d2;
//解释一下,既然大于关系能推,小于关系也应该能推,所以要建两个图
scanf("%d%d",&n,&m);
memset(d1,0x3f,sizeof(d1));
memset(d2,0x3f,sizeof(d2));
for(int i=1;i<=m;i++){
    int u,v;
    scanf("%d%d",&u,&v);
    d1[u][v]=1;
    d2[v][u]=1;
}

2、 Floyd

for(int k=1;k<=n;k++)
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            d1[i][j]=min(d1[i][k]+d1[k][j],d1[i][j]);
            d2[i][j]=min(d2[i][k]+d2[k][j],d2[i][j]);
        }

3、判断关系

int ans=0;
for(int i=1;i<=n;i++){
    int tot=0;
    for(int j=1;j<=n;j++)
        if(d1[i][j]<=0x3f3f3f30)tot++;
    if(tot>(n>>1))ans++;
    else{
        tot=0;
        for(int j=1;j<=n;j++)
            if(d2[i][j]<=0x3f3f3f30)tot++;
        if(tot>(n>>1))ans++;
    }
}
printf("%d\n",ans);

总结

看到大小关系,一般都要转换为边的关系,应用图论结论求解

posted @   Locked_Fog  阅读(346)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
主题色彩