codeforces 876E National Property (建图)

来源:互联网 发布:flexible.js使用教程 编辑:程序博客网 时间:2024/06/06 09:17

题目原文:

E. National Property

You all know that the Library of Bookland is the largest library in the world. There are dozens of thousands of books in the library.

Some long and uninteresting story was removed...

The alphabet of Bookland is so large that its letters are denoted by positive integers. Each letter can be small or large, the large version of a letter x is denoted by x'. BSCII encoding, which is used everywhere in Bookland, is made in that way so that large letters are presented in the order of the numbers they are denoted by, and small letters are presented in the order of the numbers they are denoted by, but all large letters are before all small letters. For example, the following conditions hold: 2 < 32' < 3'3' < 2.

A word x1, x2, ..., xa is not lexicographically greater than y1, y2, ..., yb if one of the two following conditions holds:

  • a ≤ b and x1 = y1, ..., xa = ya, i.e. the first word is the prefix of the second word;
  • there is a position 1 ≤ j ≤ min(a, b), such that x1 = y1, ..., xj - 1 = yj - 1 and xj < yj, i.e. at the first position where the words differ the first word has a smaller letter than the second word has.

For example, the word "3' 7 5" is before the word "2 4' 6" in lexicographical order. It is said that sequence of words is in lexicographical order if each word is not lexicographically greater than the next word in the sequence.

Denis has a sequence of words consisting of small letters only. He wants to change some letters to large (let's call this process a capitalization) in such a way that the sequence of words is in lexicographical order. However, he soon realized that for some reason he can't change a single letter in a single word. He only can choose a letter and change all of its occurrences in all words to large letters. He can perform this operation any number of times with arbitrary letters of Bookland's alphabet.

Help Denis to choose which letters he needs to capitalize (make large) in order to make the sequence of words lexicographically ordered, or determine that it is impossible.

Note that some words can be equal.

Input

The first line contains two integers n and m (2 ≤ n ≤ 100 0001 ≤ m ≤ 100 000) — the number of words and the number of letters in Bookland's alphabet, respectively. The letters of Bookland's alphabet are denoted by integers from 1 to m.

Each of the next n lines contains a description of one word in format li, si, 1, si, 2, ..., si, li (1 ≤ li ≤ 100 0001 ≤ si, j ≤ m), where li is the length of the word, and si, j is the sequence of letters in the word. The words are given in the order Denis has them in the sequence.

It is guaranteed that the total length of all words is not greater than 100 000.

Output

In the first line print "Yes" (without quotes), if it is possible to capitalize some set of letters in such a way that the sequence of words becomes lexicographically ordered. Otherwise, print "No" (without quotes).

If the required is possible, in the second line print k — the number of letters Denis has to capitalize (make large), and in the third line print k distinct integers — these letters. Note that you don't need to minimize the value k.

You can print the letters in any order. If there are multiple answers, print any of them.


解题思路:本题是伪装成字符串问题的一道图论题。

想到怎么建图比较关键。我们把每个字母当作一个节点,因为需要字典序从小到大,所以我们从上往下遍历,每次找出上下两行第一个不一样的位置,然后分情况讨论。

设上面那行为b数组,下面为 a 数组,第一个相异的位置为k。建立一个源点 s , 所有连接在这个节点上的点都是一定要被修改的, 建立一个汇点 t ,所有连接在这个节点上的点都不能被修改

b[k] > a[k]  建边 s -> b[k]  a[k] -> t

b[k] < a[k]  建边 b[k] -> a[k]   //表示b这个字符修改,a对应的字符也一定要修改


AC代码:

/** @Author: 王楚涵* @Last Modified time: 2017-10-26*/#include <bits/stdc++.h>#define inf 0x3f3f3f3f#define pb push_back#define AA first#define BB second#define ONES(x) __builtin_popcount(x)#define _  << "  " <<using namespace std;typedef pair<int, int> P;typedef long long ll ;int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0};const double eps =1e-8;const int mod = 1000000007;const double PI = acos(-1.0);inline int read(){ int num;    scanf("%d",&num);   return num;}const int maxn = 100007;int n,m,s,t;int a[maxn];int b[maxn];vector<int> e[maxn];vector<int> ans;int vis[maxn];void dfs(int u){    if(vis[u])  return;    vis[u] = 1;    if(u==t)    {puts("No"); exit(0);}    ans.pb(u);//记录那些一定要修改的点    for(int i = 0; i<e[u].size(); i++)        dfs(e[u][i]);}int main(){    scanf("%d%d",&n,&m);    s = m+1, t = m+2;    for(int i = 1; i<=n; i++){        a[0] = read();        for(int j = 1; j<=a[0]; j++)    a[j] = read();        if(i==1){            for(int k = 0; k<=a[0]; k++) b[k] = a[k];            continue;        }        int k;        for(k = 1; k<=a[0] && k<=b[0] && a[k]==b[k]; k++);//找到第一个两行相异的位置        if(k>a[0] && k<=b[0])   return 0*puts("No");        if(k<=a[0] && k<=b[0]){            if(a[k]<b[k]){//连边                e[s].pb(b[k]);                e[a[k]].pb(t);            }            else    e[a[k]].pb(b[k]);        }        for(int j = 0; j<=a[0]; j++)    b[j] = a[j];//使用滚动数组    }    dfs(s);    puts("Yes");    printf("%d\n",ans.size()-1);    for(int i = 1; i<ans.size(); i++)        printf("%d ",ans[i]);    puts("");    return 0;}/*unsigned   int   0~4294967295int   2147483648~2147483647unsigned long 0~4294967295long   2147483648~2147483647long long的最大值:9223372036854775807long long的最小值:-9223372036854775808unsigned long long的最大值:18446744073709551615__int64的最大值:9223372036854775807__int64的最小值:-9223372036854775808unsigned __int64的最大值:18446744073709551615*/


阅读全文
0 0