P5157 [USACO18DEC]The Cow Gathering

Posted lovtolzx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P5157 [USACO18DEC]The Cow Gathering相关的知识,希望对你有一定的参考价值。

题目链接

题意分析

题意

给你一棵树 每一次都会删除一个叶子节点 同时树上存在一些有向边\((a,b)\)

必须满足\(a\)\(b\)之前删除

问每一个节点作为根节点时是否存在合法的删边情况 使得跟、根节点被最后一个删除


换根\(dp\)\(No\)

首先有向边必定形成一个或者多个\(DAG\)

所以先判断是否有环

然后做做这道题 遥远的国度

以当前点作为根节点不合法的情况就是

存在有向边\((a,b)\)满足\(a\)\(b\)的祖先

那么我们对于每一条有向边分开讨论判断那些节点在当前有向边情况下可以成为根节点

同那道题 分情况讨论

1.\(a\)\(b\)的祖先

那么只有\(a\)的子树(不包括\(a\))可以成为根节点

2.\(a\)不是\(b\)的祖先

那么只有\(a\)的子树(包括\(a\))不可以成为根节点

然后我们使用\(dfs\)序实现区间覆盖就可以了

CODE:

/*-------------OI使我快乐-------------*/
int n,m,tot,cnt,top,all;
int to[M],nex[M],head[M],ans[M];
int dep[M],fath[M][20],siz[M];
int dfn[M],wt[M],tre[M],in[M];
int dfnn[M],low[M],sta[M];
bool vis[M];
vector<int> G[M];
bool flag;
IL void add_edge(int x,int y)
{;to[++tot]=y;nex[tot]=head[x];head[x]=tot;}
IL void add(int x,int y)
{for(;x<=n;x+=x&-x) tre[x]+=y;}
IL int qury(int x)
{int res=0;for(;x;x-=x&-x) res+=tre[x];return res;}
IL void dfs(int now,int fat,int deep)
{
    dep[now]=deep;fath[now][0]=fat;dfn[now]=++cnt;wt[cnt]=now;siz[now]=1;
    for(R int i=1;i<=19;++i) fath[now][i]=fath[fath[now][i-1]][i-1];
    for(R int i=head[now];i;i=nex[i])
    {
        int v=to[i];
        if(v==fat) continue;
        dfs(v,now,deep+1);
        siz[now]+=siz[v];
    }
}
IL int LCA(int nowx,int nowy)
{
    if(dep[nowx]<dep[nowy]) swap(nowx,nowy);
    for(R int i=19;i>=0;--i)
    if(dep[fath[nowx][i]]>=dep[nowy]) nowx=fath[nowx][i];
    if(nowx==nowy) return nowx;
    for(R int i=19;i>=0;--i)
    if(fath[nowx][i]!=fath[nowy][i]) 
    nowx=fath[nowx][i],nowy=fath[nowy][i];
    return fath[nowx][0];
}
IL void update(int x,int y)
{
    if(x>y) return;
    add(x,1);add(y+1,-1);
}
IL void Tarjan(int now)
{
    dfnn[now]=low[now]=++cnt;
    vis[now]=1;sta[++top]=now;
    for(R int i=0;i<(int)G[now].size();++i)
    {
        int v=G[now][i];
        if(!dfnn[v]) Tarjan(v),low[now]=min(low[now],low[v]);
        else if(vis[v]) low[now]=min(low[now],dfnn[v]);
    }
    if(low[now]==dfnn[now])
    {
        all=0;
        while(sta[top+1]!=now)
        {
            ++all;
            vis[sta[top--]]=0;
        }
        if(all>1) flag=1;
    }
}
int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    read(n);read(m);
//  puts("0");return 0;
    for(R int i=1,x,y;i<n;++i)
    {
        read(x);read(y);
        add_edge(x,y);add_edge(y,x);
    }
    dfs(1,0,1);
//  for(R int i=1;i<=n;++i) printf("%d%c",siz[i],(i==n ? '\n':' '));
    for(R int i=1,x,y;i<=m;++i)
    {
        read(x);read(y);
        G[x].push_back(y);
        int lca=LCA(x,y);
//      printf("lca=%d\n",lca);
        if(lca==x)
        {
//          puts("now cdy");
            int now=y;
            for(R int i=19;i>=0;--i)
            if(fath[now][i]&&dep[fath[now][i]]>dep[x]) now=fath[now][i];
//          printf("now at %d\n",now);
//          printf("(%d , %d)\n",dfn[now],dfn[now]+siz[now]-1);
            update(dfn[now],dfn[now]+siz[now]-1);
        }
        else
        {
//          puts("now wzy");
            update(1,dfn[x]-1);update(dfn[x]+siz[x],n);
        }
    }
    for(R int i=n;i;--i) if(!dfnn[i]) Tarjan(i);
    if(flag)
    for(R int i=1;i<=n;++i) puts("0");
//  for(R int i=1;i<=n;++i) printf("%d\n",qury(1))
    else 
    for(R int i=1;i<=n;++i) printf("%d\n",qury(dfn[i])==m);
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

HEOI 2019 RP++

以上是关于P5157 [USACO18DEC]The Cow Gathering的主要内容,如果未能解决你的问题,请参考以下文章

P2966 [USACO09DEC]牛收费路径Cow Toll Paths

bzoj4745: [Usaco2016 Dec]Cow Checklist

[BZOJ] 1648: [Usaco2006 Dec]Cow Picnic 奶牛野餐

[BZOJ1648][Usaco2006 Dec]Cow Picnic 奶牛野餐

Bzoj3893 [Usaco2014 Dec]Cow Jog

洛谷——P2853 [USACO06DEC]牛的野餐Cow Picnic