题意
给出一棵树,询问这颗树的一个拓扑序,使得给出的k个点对在拓扑序里相邻。
题解
用缩点处理每个点对,然后对缩点后的图做拓扑排序即可。
需要保证的是k个点对形成的图是若干条链,这里的判断写的有点乱。
//给出一个有向图 //求一个拓扑序 //同时k条边需要满足相邻访问 #include<bits/stdc++.h> using namespace std; const int maxn=3e5+100; vector<int> g[maxn]; int n,k; int p[maxn]; int nxt[maxn],in[maxn],pos[maxn]; int dfn[maxn],tot,inDegree[maxn]; void topOrder () { queue<int> q; for (int i=1;i<=n;i++) { if (pos[i]==i&&inDegree[i]==0) { q.push(i); } } while (q.size()) { int u=q.front(); q.pop(); int tt=u; while (tt) { dfn[++tot]=tt; tt=nxt[tt]; } for (int v:g[u]) if (--inDegree[v]==0) { q.push(v); } } } int h[maxn]; int main () { int rt; scanf("%d%d",&n,&k); for (int i=1;i<=n;i++) scanf("%d",p+i); for (int i=1;i<=k;i++) { int x,y; scanf("%d%d",&x,&y); if (nxt[x]) { return printf("0"),0; } if (in[y]) { return printf("0"),0; } nxt[x]=y; in[y]++; } for (int i=1;i<=n;i++) { if (pos[i]) continue; if (in[i]) continue; int u=i; h[u]=1; while (u) { pos[u]=i; if (nxt[u]&&h[nxt[u]]) return printf("0"),0; if (nxt[u]) h[nxt[u]]=h[u]+1; u=nxt[u]; } } //for (int i=1;i<=n;i++) printf("%d ",pos[i]); //printf(" "); for (int i=1;i<=n;i++) { if (!p[i]) rt=i; else if (pos[p[i]]==pos[i]) { if (h[i]<h[p[i]]) return printf("0"),0; continue; } else g[pos[p[i]]].push_back(pos[i]),inDegree[pos[i]]++; } //for (int i=1;i<=n;i++) if (pos[i]==i) printf("%d %d ",i,inDegree[i]); topOrder(); if (tot<n) return printf("0"),0; for (int i=1;i<=n;i++) printf("%d ",dfn[i]); }