团体天梯练习 L2-044 大众情人

发布时间 2023-04-21 00:21:05作者: Amαdeus

L2-044 大众情人

人与人之间总有一点距离感。我们假定两个人之间的亲密程度跟他们之间的距离感成反比,并且距离感是单向的。例如小蓝对小红患了单相思,从小蓝的眼中看去,他和小红之间的距离为 \(1\),只差一层窗户纸;但在小红的眼里,她和小蓝之间的距离为 \(108000\),差了十万八千里 …… 另外,我们进一步假定,距离感在认识的人之间是可传递的。例如小绿觉得自己跟小蓝之间的距离为 \(2\),则即使小绿并不直接认识小红,我们也默认小绿早晚会认识小红,并且因为跟小蓝很亲近的关系,小绿会觉得自己跟小红之间的距离为 \(1+2=3\) 。当然这带来一个问题,如果小绿本来也认识小红,或者他通过其他人也能认识小红,但通过不同渠道推导出来的距离感不一样,该怎么算呢?我们在这里做个简单定义,就将小绿对小红的距离感定义为所有推导出来的距离感的最小值。

一个人的异性缘不是由最喜欢他/她的那个异性决定的,而是由对他/她最无感的那个异性决定的。我们记一个人 \(i\) 在一个异性 \(j\) 眼中的距离感为 \(D_{ij}\) ;将 \(i\) 的“异性缘”定义为 \(1/max\) \(j∈S(i)\) { \(D_{ij}\) },其中 \(S(i)\) 是相对于 \(i\) 的所有异性的集合。那么“大众情人”就是异性缘最好(值最大)的那个人。

本题就请你从给定的一批人与人之间的距离感中分别找出两个性别中的“大众情人”。

输入格式:

输入在第一行中给出一个正整数 \(N\)\(≤500\) ),为总人数。于是我们默认所有人从 \(1\)\(N\) 编号。

随后 \(N\) 行,第 \(i\) 行描述了编号为 \(i\) 的人与其他人的关系,格式为:

性别 \(K\) 朋友 \(1\) : 距离 \(1\) 朋友 \(2\) : 距离 \(2\) …… 朋友 \(K\) : 距离 \(K\)

其中 性别 是这个人的性别,\(F\) 表示女性,\(M\) 表示男性;\(K\)\(<N\) 的非负整数)为这个人直接认识的朋友数;随后给出的是这 \(K\) 个朋友的编号、以及这个人对该朋友的距离感。距离感是不超过 \(10^{6}\) 的正整数。

题目保证给出的关系中一定两种性别的人都有,不会出现重复给出的关系,并且每个人的朋友中都不包含自己。

输出格式:

第一行给出自身为女性的“大众情人”的编号,第二行给出自身为男性的“大众情人”的编号。如果存在并列,则按编号递增的顺序输出所有。数字间以一个空格分隔,行首尾不得有多余空格。

输入样例:

6
F 1 4:1
F 2 1:3 4:10
F 2 4:2 2:2
M 2 5:1 3:2
M 2 2:2 6:2
M 2 3:1 2:5

输出样例:

2 3
4


解题思路

题目大致意思就是说,每个人对其他一些人有一定的距离感,距离感越大,则越不亲密;距离感越小,则越亲密。而且这个距离感是可以传递的,也就是说,如果一个人对另一个人没有直接的距离感,但是可以间接的通过另外一个人与其产生距离感,而且如果间接产生的距离感比直接的更小,那么两人的距离感应为间接产生的那个距离感。而我们要找出异性缘最好的男生和女生,根据题意,首先要找出每个人距离感最大的异性(前提是可以直接或间接产生距离感),然后找出这里面最大距离感最小的人的序列(男女生分开)。

而这个距离感,其实就是点与点之间的距离,“异性缘”定义为 \(1/max\) \(j∈S(i)\) { \(D_{ij}\) },其中 \(S(i)\) 是相对于 \(i\) 的所有异性的集合,很显然我们就是要找出最大距离感最小的人的序列。

这道题的点的数量不是很多,所以这道题可以用 \(Floyd\) 求解出全源最短路,并且分别找出男生和女生的最小的最大距离。然后找出符合这个指标的男生和女生,最后输出答案即可。这道题代码量稍大,但是实现还是比较容易的。但是有一点需要注意,计算异性缘时的距离感是别人对自己的距离感,所以如果在更新 \(u\) 的最大距离感时,此时需要枚举异性 \(v\)\(dist[v][u]\) 来更新。

/*   一切都是命运石之门的选择  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 = 510;
int dist[N][N], n;
int a[N];   //a[u]表示u与所有可以到达的异性的最大距离感
int ansm = inf, ansf = inf;  //记录最大距离感的最小值
char gen[N];//记录每个人的性别
vector<int> vm, vf;   //分别存储男性大众情人 女性大众情人

void init(){
    for(int i = 1; i <= n; i ++ )
        for(int j = 1; j <= n; j ++ )
            if(i != j) dist[i][j] = inf;
}

void floyd(){
    for(int k = 1; k <= n; k ++ )
        for(int i = 1; i <= n; i ++ )
            for(int j = 1; j <= n; j ++ )
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
}

void show(){
    for(int i = 1; i <= n; i ++ ){
        if(a[i] == ansm && gen[i] == 'M') vm.push_back(i);
        if(a[i] == ansf && gen[i] == 'F') vf.push_back(i);
    }

    //输出女性大众情人
    for(int i = 0; i < (int)vf.size() - 1; i ++ ) cout << vf[i] << ' ';
    cout << vf.back() << endl;
    //输出男性大众情人
    for(int i = 0; i < (int)vm.size() - 1; i ++ ) cout << vm[i] << ' ';
    cout << vm.back() << endl;
}

int main(){
    //ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    cin >> n;
    init();

    for(int u = 1; u <= n; u ++ ){
        cin >> gen[u];
        int k; cin >> k;
        while(k -- ){
            int v, d; scanf("%d:%d", &v, &d);
            dist[u][v] = d;
        }
    }

    floyd();

    for(int u = 1; u <= n; u ++ ){
        for(int v = 1; v <= n; v ++ )
            if(gen[u] != gen[v])
                a[u] = max(a[u], dist[v][u]);  //注意是别人对自己的距离感
        if(gen[u] == 'M') ansm = min(ansm, a[u]);
        if(gen[u] == 'F') ansf = min(ansf, a[u]);
    }

    show();

    return 0;
}