QZEZOJ 环游QZ题解--zhengjun

题目描述

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

输入

第一行两个数\(n\)\(m\)表示地方数、边数
第二行n个数表示\(n\)个地点的\(happy\)
然后m行每行两个数\(a\)\(b\)表示\(a\)\(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\)
对于30%的数据:\(1<=n<=500,1<=m<=2500\)
对于60%的数据:\(1<=n<=1000,m<=3000\)
对于100%的数据:\(1<=n<=10^5,1<=m<=2*10^5\)\(happy\)值小于等于2^31-1

思路

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

条条大路通罗马

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

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

首先,我就将各个地方按照\(happy\)值升序排个序,接下来,我就安排序后的顺序,一个一个做。找到能当前节点的所有点,判断是否满足\(happy\)值比当前节点大,如果是,就更新当前节点的\(f\)数组\((f_x=max(f_x,f_t+1))\)。最后,在\(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

posted @ 2022-06-10 18:15  A_zjzj  阅读(33)  评论(0编辑  收藏  举报