codeforces 681D Gifts by the List dfs+构造

题意:给你一个森林,表示其祖先关系(自己也是自己的祖先),每个人有一个礼物(要送给这个人的固定的一个祖先)

          让你构造一个序列,使得的对于每个人,这个序列中第一个出现的他的祖先,是他要送礼物的的那个祖先

分析:这个序列满足

           1:我们这个序列只需要出现那些被送礼物的人就好了

           2:这个序列的元素保证,如果x是y的祖先,那么x在y的后面

具体:这个序列可以通过dfs构造,然后最后check一下这个序列

注:check的过程和构造序列的dfs过程同步

#include <cstdio>
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <map>
#include <stack>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
const int N=1e5+5;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
struct Edge{
  int v,next;
}edge[N];
int head[N],tot,d[N],n,m,a[N],ret[N];
void add(int u,int v){
  edge[tot].v=v;
  edge[tot].next=head[u];
  head[u]=tot++;
}
stack<int>s;
bool vis[N];
void dfs(int u,int fir){
  if(vis[u])fir=u,s.push(u);
  ret[u]=fir;
  for(int i=head[u];~i;i=edge[i].next)
    dfs(edge[i].v,fir);
}
int main(){
   scanf("%d%d",&n,&m);
   memset(head,-1,sizeof(head));
   for(int i=0;i<m;++i){
    int u,v;
    scanf("%d%d",&u,&v);
    ++d[v];add(u,v);
   }
   for(int i=1;i<=n;++i){
    scanf("%d",&a[i]);
    vis[a[i]]=true;
   }
   for(int i=1;i<=n;++i)
    if(!d[i])dfs(i,i);
   for(int i=1;i<=n;++i)
    if(ret[i]!=a[i]){printf("-1
");return 0;}
   printf("%d
",s.size());
   while(!s.empty()){
    printf("%d
",s.top());
    s.pop();
   } 
   return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuguangzw/p/5614350.html