CF 876E-National Property

题意简述

给你n个数字串,刚开始每个数字的优先级为2,你要把某些数字的优先级设为1,然后使得得这些串不降,就是后面一个串要大于等于前面一个串,这个判断大小就是按位比较,先比较优先级,然后比较大小。

做法

为了方便叙述,我们把优先级为1的叫做大写,优先级为2的叫做小写。
我们把每个串i和他前面一个串i-1比较,找到第一个不相同的位置j,分类讨论一波
1.如果 a [ i ] [ j ] > a [ i 1 ] [ j ] ,说明如果a[i][j]是大写,那么a[i-1][j]是大写,所以从a[i][j]向a[i-1][j]连一条边。
2.如果 a [ i ] [ j ] < a [ i 1 ] [ j ] ,说明a[i-1][j]必须是大写,a[i][j]必须是小写,所以S向a[i-1][j]连边,a[i][j]向T连边。
还要注意一点,如果i这个串是i-1这个串的前缀,肯定无解,这个可以直接判掉

遍历完所有边之后,我们得到了一张图,然后我们从S开始BFS,能够走到的点都必须是大写。
如果能走到T,说明无解,这是显然的。
那么最后我们只要把所有S能遍历到的点输出来就行了。

#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<iostream>
#include<cmath>
#include<vector>
#define LL long long
#define INF (2139062143)
#define N (100001)
using namespace std;
int n,m,x,S,T,cnt,tot,h,t; 
int len[N],head[N],son[N<<3],nxt[N<<3],ans[N],q[N<<3];
bool vis[N]; 
vector <int> a[N];
template <typename T> void read(T&t) {
    t=0;
    bool fl=true;
    char p=getchar();
    while (!isdigit(p)) {
        if (p=='-') fl=false;
        p=getchar();
    }
    do {
        (t*=10)+=p-48;p=getchar();
    }while (isdigit(p));
    if (!fl) t=-t;
}
inline void add(int x,int y){
    son[++tot]=y,nxt[tot]=head[x],head[x]=tot;
}
int main(){
    read(n),read(m);
    for (int i=1;i<=n;i++){
        read(len[i]);
        a[i].push_back(0);
        for (int j=1;j<=len[i];j++){
            read(x);
            a[i].push_back(x);
        } 
    }
    S=m+1,T=m+2;
    for (int i=2;i<=n;i++){
        bool over=0;
        for (int j=1;j<=min(len[i],len[i-1]);j++){
            if (a[i][j]!=a[i-1][j]){
                if (a[i-1][j]>a[i][j]){
                    add(S,a[i-1][j]);
                    add(a[i][j],T);
                }
                else{
                    add(a[i][j],a[i-1][j]);
                }
                over=1;
                break;
            }
        }
        if (!over){
            if (len[i]<len[i-1]){
                puts("No");
                return 0;
            }
        }
    }
    h=t=0;
    q[++t]=S;
    while (h<t){
        int u=q[++h];
        for (int p=head[u];p;p=nxt[p]){
            if (!vis[son[p]]){
                vis[son[p]]=1;
                q[++t]=son[p];
            }
        }
    }
    if (vis[T]){
        puts("No");
    }
    else{
        for (int i=1;i<=m;i++){
            if (vis[i]) ans[++cnt]=i;
        }
        puts("Yes");
        printf("%d\n",cnt);
        for (int i=1;i<=cnt;i++) printf("%d ",ans[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36056315/article/details/80310662