Game Leader HDU - 6002

题目链接

题意:有一个社交网络,每个玩家都有一个评分而且评分不同,一些玩家可以结交成朋友,朋友是相对而言的,意思就是说如果A是B的朋友,那么B也是A的朋友,每个玩家都有一个评分排名,他们知道自己的排名以及自己朋友的排名, Tom有n个朋友, 他在n个朋友中的排名是R,现在已知Tom朋友列表中有M对朋友,排名为Xi和排名为Yi的朋友互为朋友,还知道Tom列表中的排名为i的朋友,i在Ci个他的朋友的列表上评分占第一名,现在要求最少有多少个人是Tom的陌生人但是陌生人的朋友列表上评分排第一名的是Tom的朋友 来自题意

思路:超棒

每个朋友当第一的次数已经告诉你了是固定值,要求多少主人是陌生人,但排名第一是朋友的列表最少为多少。每个朋友当第一的次数有两部分组成,一部分是在陌生人列表里当第一,另一部分是在朋友列表里当第。一部分少,另一部分自然就多了,我们就可以求出每个朋友最多在朋友列表里当第一的次数。每个朋友当第一的次数 - 最多在朋友列表里当第一的次数 = 最少在陌生人列表里当第一的次数,然后累加求和就可以了。

f[i] 表示编号为i的朋友他的列表第一至少应该是编号为f[i]的人,这里,f[i]在i的朋友中优先选取Tom的朋友,因此两次用到f数组,第一次时i的朋友中有i和Tom,i和Tom嘛就选编号小的那个了。第二次是在输入朋友关系时,如果知道某个人是i的朋友,此时比较一下这个人的编号和f[i]那个小 f[x] = min(f[x],y);f[y] = min(f[y],x);

num[i]就表示i最多在朋友列表里当第一的次数

#include<bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
#define maxn 100010
using namespace std;
int ran[maxn],f[maxn],num[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    for(int k = 1;k <= T;k++)
    {
        int n,m,r;
        LL ans = 0;
        scanf("%d%d%d",&n,&m,&r);
        memset(f,0,sizeof(f));
        memset(num,0,sizeof(num));
        for(int i = 1;i <= n;i++)
        {
            scanf("%d",&ran[i]);
            f[i] = min(i,r);//有点意思
        }
        f[r] = 1;
        for(int i = 1;i <= m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            f[x] = min(f[x],y);
            f[y] = min(f[y],x);
        }
        for(int i = 1;i <= n;i++) num[f[i]]++;
        for(int i = 1;i <= n;i++) ans = max(ans + ran[i] - num[i],0LL);
        printf("Case #%d: %I64d\n",k,ans);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值