环游QZ题解--zhengjun

题目描述

F L Y FLY FLY想要带着他新叫的朋友环游 Q Z QZ QZ,于是他把 Q Z QZ QZ划分成了 n n n个地方,已知这 n n n个地方由 m m m条双向边相连接,并且他把 n n n个地方分别赋予了一个 h a p p y happy happy值,他希望按照 h a p p y happy happy值严格递减 ( a > b ) (a>b) a>b的方法去游览 Q Z QZ QZ,这样他可以把一些最美的地方介绍给他朋友。如果能够游览的地方数超过10^9+7则输出infinity

输入

第一行两个数 n n n m m m表示地方数、边数
第二行n个数表示 n n n个地点的 h a p p y happy happy
然后m行每行两个数 a a a b b b表示 a a a b b b之间有一条无向边

输出

一行一个数表示最多能够游览的地方数或者infinity

样例输入
10 30
720472486 1616090782 1659830133 376600248 1485380712 819748825 1072214931 1957734249 95302927 622052677 
2 6 
1 6 
10 2 
8 4 
8 2 
9 6 
1 4 
9 7 
1 4 
4 7 
7 1 
4 5 
10 6 
7 7 
8 5 
7 8 
6 2 
7 2 
3 9 
6 8 
3 4 
9 8 
8 8 
4 5 
8 7 
5 6 
2 2 
9 7 
3 1 
9 1 
样例输出
5
提示

对于10%的数据: 1 < = n < = 10 , 1 < = m < = 30 1<=n<=10,1<=m<=30 1<=n<=101<=m<=30
对于30%的数据: 1 < = n < = 500 , 1 < = m < = 2500 1<=n<=500,1<=m<=2500 1<=n<=5001<=m<=2500
对于60%的数据: 1 < = n < = 1000 , m < = 3000 1<=n<=1000,m<=3000 1<=n<=1000m<=3000
对于100%的数据: 1 < = n < = 1 0 5 , 1 < = m < = 2 ∗ 1 0 5 1<=n<=10^5,1<=m<=2*10^5 1<=n<=1051<=m<=2105 h a p p y happy happy值小于等于2^31-1

思路

首先表明,我的思路并不是正解,但是

条条大路通罗马

我的方法也许会给你一点启示。

用一个 f f f数组记录每个地方最多能够游览的地方,数,初始化为1。

首先,我就将各个地方按照 h a p p y happy happy值升序排个序,接下来,我就安排序后的顺序,一个一个做。找到能当前节点的所有点,判断是否满足 h a p p y happy happy值比当前节点大,如果是,就更新当前节点的 f f f数组 ( f x = m a x ( f x , f t + 1 ) ) (f_x=max(f_x,f_t+1)) fx=max(fxft+1)。最后,在 f f f数组中找一个最大的数,就是答案。

代码

#include<bits/stdc++.h>
#define maxn 100039
#define maxm 1000039
#define max(x,y) (x>y?x:y)
using namespace std;
int n,m;
struct zj{
    int happy,num,ans=1;//happy值,原来的编号,答案
}f[maxn];
int nex[maxm],to[maxm],head[maxn],k;
void add(int a,int b)//链式前向星
{
    to[k]=b;
    nex[k]=head[a];
    head[a]=k++;
    return;
}
bool cmp(const zj &x,const zj &y)
{
    return x.happy<y.happy;
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&f[i].happy),f[i].num=i;
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
        //题中说是双向边
    }
    int w[maxn];//记录原来节点的排序后位置
    sort(a+1,a+1+n,cmp);//排序
    for(int i=1;i<=n;i++)
        w[f[i].num]=i;//记录位置
    int ans=0;//最终答案
    for(int i=1;i<=n;i++)
    {
        int pos=head[f[i].num],t=0;
        while(pos!=-1)
        {
            if(f[w[to[pos]]].happy<f[i].happy)//满足题中条件
            t=max(t,f[i].ans+f[w[to[pos]]].ans);//更新当前节点的答案
            pos=nex[pos];
        }
        t=max(t,a[i].ans);
        a[i].ans=t;
        ans=max(ans,t);//更新最终答案
    }
    if(ans>1000000007)cout<<"infinity";
    else cout<<ans;
    return 0;
}

谢谢大家–zhengjun

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A_zjzj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值