Codeforces 770C Online Courses In BSU【思维+拓扑排序+Dfs重建图】

C. Online Courses In BSU time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output

Now you can take online courses in the Berland State University! Polycarp needs to pass k main online courses of his specialty to get a diploma. In total n courses are availiable for the passage.

The situation is complicated by the dependence of online courses, for each course there is a list of those that must be passed before starting this online course (the list can be empty, it means that there is no limitation).

Help Polycarp to pass the least number of courses in total to get the specialty (it means to pass all main and necessary courses). Write a program which prints the order of courses.

Polycarp passes courses consistently, he starts the next course when he finishes the previous one. Each course can’t be passed more than once.

Input

The first line contains n and k (1 ≤ k ≤ n ≤ 105) — the number of online-courses and the number of main courses of Polycarp’s specialty.

The second line contains k distinct integers from 1 to n — numbers of main online-courses of Polycarp’s specialty.

Then n lines follow, each of them describes the next course: the i-th of them corresponds to the course i. Each line starts from the integer ti (0 ≤ ti ≤ n - 1) — the number of courses on which the i-th depends. Then there follows the sequence of ti distinct integers from 1 to n — numbers of courses in random order, on which the i-th depends. It is guaranteed that no course can depend on itself.

It is guaranteed that the sum of all values ti doesn’t exceed 105.

Output

Print -1, if there is no the way to get a specialty.

Otherwise, in the first line print the integer m — the minimum number of online-courses which it is necessary to pass to get a specialty. In the second line print m distinct integers — numbers of courses which it is necessary to pass in the chronological order of their passage. If there are several answers it is allowed to print any of them.

Examples Input

6 2
5 3
0
0
0
2 2 1
1 4
1 5

Output

5
1 2 3 4 5 

Input

9 3
3 9 5
0
0
3 9 4 5
0
0
1 8
1 6
1 2
2 1 2

Output

6
1 2 9 4 5 3 

Input

3 3
1 2 3
1 2
1 3
1 1

Output

-1

Note

In the first test firstly you can take courses number 1 and 2, after that you can take the course number 4, then you can take the course number 5, which is the main. After that you have to take only the course number 3, which is the last not passed main course. 

题目大意:

一共有N个科目,其中有M个主要科目,只要M个主要科目都通过了,那么对应主人公就可以毕业了,也就是达成了目的。

现在有一个列表,表示要通过第i门课程需要先通过的科目列表。现在主人公希望得到一个通过科目的顺序,使得最终他通过最少的科目使得主人公毕业。

思路(感觉我这个思路有点偏向个人化,应该有更优的做法):

1、首先建图Dfs.维护一个数组have【i】,表示修完第i们课程之后可以进修的课程中,有没有主要科目(那M个科目中的任意一些);如果有,维护为have【i】==1

否则have【i】==0.

接下来根据Dfs得到的信息进行重新建图,即对于一条边u,v.如果have【v】==1,那么对应这条边就需要保留下来(因为主修科目一定要修),同理,如果have【v】==0.那么这条边就不需要了,直接删除即可(因为之后再修课程没有收益)。

2、那么对于重新建立的图直接跑拓扑排序记录过程即可,这个过程就可以作为一个顺序作为答案。

3、需要注意几个小细节:

①注意环。

②注意重新建图之后跑出来的结果是否能够毕业。

③注意重新建图之后跑出来的结果有没有多的。

Ac代码:

#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
int vis[105000];
int have[105000];
int degree[105000];
vector<int >mp[105000];
vector<int >mp2[105000];
int ned[105000];
int ans[105000];
int n,m;
void Getmap()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<mp[i].size();j++)
        {
            int v=mp[i][j];
            mp2[i].push_back(v);
        }
        mp[i].clear();
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<mp2[i].size();j++)
        {
            int v=mp2[i][j];
            if(have[v]==0)continue;
            else mp[i].push_back(v);
        }
    }
}
void Dfs(int u)
{
    vis[u]=1;
    if(ned[u]==1)have[u]=1;
    for(int i=0;i<mp[u].size();i++)
    {
        int v=mp[u][i];
        if(vis[v]==0)
        {
            Dfs(v);
        }
        have[u]=max(have[u],have[v]);
    }
    for(int i=0;i<mp[u].size();i++)
    {
        int v=mp[u][i];
        if(have[v]==0)mp[u].erase(mp[u].begin()+i);
    }
}
void Slove_top()
{
    int sum=0;
    queue<int >s;
    for(int i=1;i<=n;i++)
    {
        if(have[i]==1)sum++;
        if(degree[i]==0&&have[i]==1)s.push(i);
    }
    int cnt=0;
    while(!s.empty())
    {
        int u=s.front();
        s.pop();
        ans[cnt++]=u;
        for(int i=0;i<mp[u].size();i++)
        {
            int v=mp[u][i];
            degree[v]--;
            if(degree[v]==0)
            {
                s.push(v);
            }
        }
    }
    if(cnt==sum&&cnt>=m)
    {
        printf("%d\n",cnt);
        for(int i=0;i<cnt;i++)
        {
            printf("%d ",ans[i]);
        }
        printf("\n");
    }
    else printf("-1\n");
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(ned,0,sizeof(ned));
        memset(degree,0,sizeof(degree));
        for(int i=1;i<=n;i++)mp[i].clear();
        for(int i=1;i<=n;i++)mp2[i].clear();
        for(int i=0;i<m;i++)
        {
            int x;
            scanf("%d",&x);ned[x]++;
        }
        for(int i=1;i<=n;i++)
        {
            int k;
            scanf("%d",&k);
            while(k--)
            {
                int v;
                scanf("%d",&v);
                mp[v].push_back(i);
                degree[i]++;
            }
        }
        int flag=0;
        memset(vis,0,sizeof(vis));
        memset(have,0,sizeof(have));
        for(int i=1;i<=n;i++)
        {
            if(degree[i]==0)
            {
                flag=1;
                Dfs(i);
            }
        }
        Getmap();
        if(flag==0)
        {
            printf("-1\n");
            continue;
        }
        Slove_top();
    }
}

    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/mengxiang000000/article/details/66474594
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞