题目描述:
qwq…
题目分析:
二分 拓扑 保证字典序最小 最后搞优先队列输出就好啦
题目链接:
Ac 代码:
#include <cstdio>
#include <queue>
#include <iostream>
#include <cstring>
#include <vector>
const int maxm=5e5+100;
int n,m;
int head[maxm],to[maxm<<1],net[maxm<<1],r[maxm],vis[maxm],cnt;
std::vector <int> q[maxm];
inline void addedge(int u,int v)
{
cnt++;
to[cnt]=v,net[cnt]=head[u],head[u]=cnt;
}
struct node{
int id;
node(int b):id(b){}
inline bool operator < (const node&a) const
{
return a.id<id;
}
};
std::priority_queue <node> dl;
inline void build(int mid)
{
cnt=0;
memset(head,0,sizeof(head));
memset(r,0,sizeof(r));
memset(vis,0,sizeof(vis));
for(int i=1;i<=mid;i++)
for(int j=0;j<q[i].size()-1;j++)
addedge(q[i][j],q[i][j+1]),r[q[i][j+1]]++;
}
inline bool topsort(int f)
{
int sum=0;
for(int i=1;i<=n;i++)
if(!r[i])
{
sum++;
dl.push((node){i}),vis[i]=1;
}
while(!dl.empty())
{
node now=dl.top();
if(f) printf("%d ",now.id);
dl.pop();
for(int i=head[now.id];i;i=net[i])
{
r[to[i]]--;
if(!r[to[i]]&&!vis[to[i]]) dl.push((node){to[i]}),sum++,vis[to[i]]=1;
}
}
return sum==n;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int s;
scanf("%d",&s);
for(int j=1,x;j<=s;j++)
scanf("%d",&x),q[i].push_back(x);
}
int l=0,r=m+1;
int ans=0;
while(l<=r)
{
int mid=(l+r)>>1;
build(mid);
if(topsort(0)) l=mid+1,ans=mid;
else r=mid-1;
}
build(ans);
topsort(1);
return 0;
}