大众情人
人与人之间总有一点距离感。
我们假定两个人之间的亲密程度跟他们之间的距离感成反比,并且距离感是单向的。
例如小蓝对小红患了单相思,从小蓝的眼中看去,他和小红之间的距离为 1 1 1,只差一层窗户纸;但在小红的眼里,她和小蓝之间的距离为 108000 108000 108000,差了十万八千里……
另外,我们进一步假定,距离感在认识的人之间是可传递的。
例如小绿觉得自己跟小蓝之间的距离为 2 2 2,则即使小绿并不直接认识小红,我们也默认小绿早晚会认识小红,并且因为跟小蓝很亲近的关系,小绿会觉得自己跟小红之间的距离为 1 + 2 = 3 1+2=3 1+2=3。
当然这带来一个问题,如果小绿本来也认识小红,或者他通过其他人也能认识小红,但通过不同渠道推导出来的距离感不一样,该怎么算呢?
我们在这里做个简单定义,就将小绿对小红的距离感定义为所有推导出来的距离感的最小值。
一个人的异性缘不是由最喜欢他/她的那个异性决定的,而是由对他/她最无感的那个异性决定的。
我们记一个人
i
i
i 在一个异性
j
j
j 眼中的距离感为
D
i
j
D_{ij}
Dij;将
i
i
i 的“异性缘”定义为
1
/
m
a
x
j
∈
S
(
i
)
{
D
i
j
}
1/max_{j \in S(i)}\{D_{ij}\}
1/maxj∈S(i){Dij},其中
S
(
i
)
S(i)
S(i) 是相对于
i
i
i 的所有异性的集合。
那么“大众情人”就是异性缘最好(值最大)的那个人。
本题就请你从给定的一批人与人之间的距离感中分别找出两个性别中的“大众情人”。
输入格式
输入在第一行中给出一个正整数 N N N,为总人数。于是我们默认所有人从 1 1 1 到 N N N 编号。
随后
N
N
N 行,第
i
i
i 行描述了编号为
i
i
i 的人与其他人的关系,格式为:
性别 K 朋友1:距离1 朋友2:距离2 …… 朋友K:距离K
其中 性别 是这个人的性别,F 表示女性,M 表示男性;K(KaTeX parse error: Expected 'EOF', got '&' at position 1: &̲lt;N 的非负整数)为这个人直接认识的朋友数;随后给出的是这 K 个朋友的编号、以及这个人对该朋友的距离感。
距离感是不超过 1 0 6 10^6 106 的正整数。
题目保证给出的关系中一定两种性别的人都有,不会出现重复给出的关系,并且每个人的朋友中都不包含自己。
输出格式
第一行给出自身为女性的“大众情人”的编号,第二行给出自身为男性的“大众情人”的编号。
如果存在并列,则按编号递增的顺序输出所有。
数字间以一个空格分隔,行首尾不得有多余空格。
数据范围
1 ≤ N ≤ 500 1 \le N \le 500 1≤N≤500
输入样例
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
思路
这道题就说某点到某点的距离,再看看数据范围,再结合实际生活(没有环),那么我们可以推断用的是flord。
但题目有很多细节:
- 细节1:叫我们求的是 1 / m a x j ∈ S ( i ) { D i j } 1/max_{j \in S(i)}\{D_{ij}\} 1/maxj∈S(i){Dij}的最大值,因此我们得分开求,也就是先求 { D i j } \{D_{ij}\} {Dij}的最小值,然后再求 m a x j ∈ S ( i ) { D i j } max_{j \in S(i)}\{D_{ij}\} maxj∈S(i){Dij},进而再求整个分式的最大值,那么我们就让 m a x j ∈ S ( i ) { D i j } max_{j \in S(i)}\{D_{ij}\} maxj∈S(i){Dij}最小。因此这道题就很好做了。
- 细节2:我们记一个人
i
i
i 在一个异性
j
j
j 眼中的距离感为
D
i
j
D_{ij}
Dij,注意这句话,因此在后面求最大最小值的时候(代码有注释),一定要
dist[j][i]
,不要写反了。
代码
//思路:有点flord的样子,但多了什么异性缘,因此本题求最短路
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 510,INT = 0x3f3f3f3f;
int dist[N][N];
int n;
int sex[N];//女生为1,男生为0
int wowan[N],man[N],cw,cm;
int d[N];
int main(){
cin>>n;
memset(dist,0x3f,sizeof dist);
//可达点标记
for(int i=1;i<=n;i++){
dist[i][i]=0;
string sx;
int k;
cin>>sx>>k;
if(sx=="F")sex[i]=1;
else sex[i]=0;
for(int j=0;j<k;j++){
int fd,d;
scanf("%d:%d",&fd,&d);
dist[i][fd]=d;
}
}
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]);
}
}
}
//求出题目所说的分母max()
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if((sex[i]^sex[j])){
d[i]=max(d[i],dist[j][i]);//一个人i在一个异性j眼中的距离感
}
}
}
int dwoman=INT,dman=INT;
//现在求整个分式(因为要使得整个分式最大,那么要让分母的max最小)
for(int i=1;i<=n;i++){
if(sex[i]){
dwoman=min(dwoman,d[i]);
}else{
dman=min(dman,d[i]);
}
}
for(int i=1;i<=n;i++){
if(sex[i]){
if(dwoman==d[i]){
wowan[cw++]=i;
}
}else{
if(dman==d[i]){
man[cm++]=i;
}
}
}
for(int i=0;i<cw;i++){
cout<<wowan[i]<<" ";
}
cout<<endl;
for(int i=0;i<cm;i++){
cout<<man[i]<<" ";
}
return 0;
}