fzyzoiP4947 分班(题解)

 本来要开specialjudge的,可是蒟蒻出题人懒,于是改成了输出字典序最小的访问顺序

题目意思总结:

给出一个图,每个顶点有一个目标权值,要求设计一个字典序最小的访问顺序,使得节点被访问时的权值是目标权值。节点当前权值设定为与它相连的所有节点中已被访问的节点的权值之外的最小值。

 

贪心。

进行分析,可以得出若有一条路径,一定是按班级编号从小到大进行遍历(注意题面中对遍历顺序没有限制),排序一下即可。

再想什么时候可以走出这一条路径,必须满足该条件:

设该妹子原来计划去的班级编号为k,则对于她的所有的朋友一定包括1-(k-1)的所有编号且一定不包括k。 

(正确性再看一遍题面意思总结即可明白)

时间复杂度理论上为O(n)

 

下面给出AC代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN=500005;
vector<int> q[MAXN];
struct sisterz{
    int classs;
    int num;
}a[MAXN];
bool flag[MAXN];
int n,m;
int fastread(){
    int ans=0;
    char p=getchar();
    while(p<'0'||p>'9')
    p=getchar();
    while(p>='0'&&p<='9'){
        ans=ans*10+(p-'0');
        p=getchar();
    }
    return ans;
}
bool cmp(sisterz aa,sisterz bb){
    if(aa.classs<bb.classs)
    return true;
    if(aa.classs==bb.classs&&aa.num<bb.num)
        return true;
    return false;
}
int main(){
    int ai,bi;
    //freopen("class18.in","r",stdin);
//    freopen("class18.ans","w",stdout);
    n=fastread();
    m=fastread();
    for(int i=1;i<=m;i++){
        ai=fastread();
        bi=fastread();
        q[ai].push_back(bi);
        q[bi].push_back(ai);
    }
    for(int i=1;i<=n;i++){
        a[i].classs=fastread();
        a[i].num=i;
    }
    for(int i=1;i<=n;i++){
        for(size_t j=0;j<q[i].size();j++)
            flag[a[q[i][j]].classs]=1;
        for(int j=1;j<a[i].classs;j++)
            if(flag[j]==0){
                printf("No\n");
                return 0;
            }
        if(flag[a[i].classs]==1){
            printf("No\n");
            return 0;
        }
        for(size_t j=0;j<q[i].size();j++)
            flag[a[q[i][j]].classs]=0;
    }
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++)
        printf("%d ",a[i].num);
    printf("\n");
    return 0;
}

 

posted @ 2020-06-15 21:23  aerovnane  阅读(243)  评论(0)    收藏  举报