CodeForces 29D Ant on the Tree

给一颗树,1为根,要求遍历树上所有点,给出叶子结点的访问顺序,限制每条边至多访问两次。

首先这是一棵树,那么两点之间的路线是确定的,所以我第一遍dfs预处理出从根节点到每个叶子的路径保存,以便后面输出。

那么就按照题目要求输出叶子结点的顺序依次输出,然后从一个叶子到下一个叶子的时候,从他们的最近公共祖先转折,所以我还预处理了相邻两个叶子结点的LCA。

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
#pragma comment(linker, "/STACK:16777216")
#define eps 1e-6
#define ll long long
using namespace std;

const int maxn=310;
struct node
{
    int v,id,w;//id为边号或询问号
    node* next;
}ed[maxn<<2],*head[maxn],*q[maxn];

struct qnode
{
    int u,v,ans;//存询问结点,ans最近公共祖先
} qu[maxn];

int fa[maxn],vis[maxn],cnt;

void init(int n)
{
    cnt=0;
    memset(vis,0,sizeof vis);
    memset(head,0,sizeof head);
    memset(q,0,sizeof q);
    for(int i=0;i<=n;i++)
        fa[i]=i;
}

int getfa(int x)
{
    if(fa[x]==x) return x;
    return fa[x]=getfa(fa[x]);
}

void LCA(int u)
{
    fa[u]=u,vis[u]=1;
    for(node *p=q[u];p!=NULL;p=p->next)
    {
        if(vis[p->v])
        {
            int id=p->id;
            qu[id].ans=getfa(p->v);
        }
    }
    for(node *p=head[u];p!=NULL;p=p->next)
    {
        if(!vis[p->v])
        {
            LCA(p->v);
            fa[p->v]=u;
        }
    }
}

void adde(node *e[],int u,int v,int w,int id)//建边e传头节点数组。为询问边的或树边的。
{
    ed[cnt].v=v;
    ed[cnt].w=w;
    ed[cnt].id=id;
    ed[cnt].next=e[u];
    e[u]=&ed[cnt++];
}

inline int ReadInt()
{
    char ch = getchar();
    if (ch==EOF) return -1;
    int data = 0;
    while (ch < '0' || ch > '9')
    {
        ch = getchar();
        if (ch==EOF) return -1;
    }
    do
    {
        data = data*10 + ch-'0';
        ch = getchar();
    } while (ch >= '0' && ch <= '9');
    return data;
}

int f[maxn],leaf[maxn],ans[610],flag;

void dfs(int s)
{
    for(node *p=head[s];p!=NULL;p=p->next)
    {
        if(!vis[p->v])
        {
            vis[p->v]=1;
            f[p->v]=s;
            dfs(p->v);
        }
    }
}

void output(int s,int t)//r->leaf
{
    if(f[t]!=s)
        output(s,f[t]);
    ans[cnt++]=t;
    flag++;
}

void output1(int s,int t)//leaf->r
{
    do
    {
        flag++;
        ans[cnt++]=f[s];
        s=f[s];
    }while(s!=t);
}

int main()
{
    int n,a,b,i,k;
    scanf("%d",&n);
    init(n);
    for(i=0;i<n-1;i++)
    {
        scanf("%d%d",&a,&b);
        adde(head,a,b,1,i);
        adde(head,b,a,1,i);
    }
    k=0;
    while((leaf[k]=ReadInt())!=-1) k++;
    for(i=1;i<k;i++)
    {
        adde(q,leaf[i],leaf[i-1],1,i);
        adde(q,leaf[i-1],leaf[i],1,i);
    }
    LCA(1);

    memset(vis,0,sizeof vis);
    memset(f,-1,sizeof f);
    vis[1]=1;
    dfs(1);

    cnt=0;flag=1;
    ans[cnt++]=1;
    output(1,leaf[0]);
    if(flag<=n+n-1)
        for(i=1;i<k;i++)
        {
            output1(leaf[i-1],qu[i].ans);
            if(flag>n+n-1) break;
            output(qu[i].ans,leaf[i]);
            if(flag>n+n-1) break;
        }
    if(flag<=n+n-1) output1(leaf[k-1],1);
    if(flag<=n+n-1)
    {
        printf("1");
        for(i=1;i<cnt;i++)
            printf(" %d",ans[i]);
        puts("");
    }
    else printf("-1\n");
    return 0;
}

CodeForces 29D Ant on the Tree

时间: 2024-10-29 10:46:13

CodeForces 29D Ant on the Tree的相关文章

Codeforces 29D Ant on the Tree 树的遍历 dfs序

题目链接:点击打开链接 题意: 给定n个节点的树 1为根 则此时叶子节点已经确定 最后一行给出叶子节点的顺序 目标: 遍历树并输出路径,要求遍历叶子节点时按照给定叶子节点的先后顺序访问. 思路: 给每个节点加一个优先级. 把最后一个叶子节点到父节点的路径上的点优先级改为1 把倒数第二个叶子节点到父节点的路径上的点优先级改为2 如此每个点就有一个优先级,每个访问儿子节点时先访问优先级大的即可 对于无解的判断:得到的欧拉序列不满足输入的叶子节点顺序即是无解. #include <cstdio> #

codeforces 514E Darth Vader and Tree (dp+快速幂)

codeforces 514E Darth Vader and Tree (dp+快速幂) 题意: 有一棵树,每个节点有n个儿子,给出父亲到每个儿子的距离di,问离祖先距离不超过x的子孙有多少个(子孙包括祖先)对1e9+7取模. 限制: 1 <= n <= 1e5; 0 <= x <= 1e9; 1 <= di <= 100 思路: 因为di <= 100,所以可以用快速幂来处理这道题, 大概过程为:先用dp算出前100的答案,剩下的用快速幂来处理.

codeforces 220 C. Game on Tree

题目链接 codeforces 220 C. Game on Tree 题解 对于 1节点一定要选的 发现对于每个节点,被覆盖切选中其节点的概率为祖先个数分之一,也就是深度分之一 代码 #include<cstdio> #include<algorithm> const int maxn = 1000007; struct node { int u,v,next; } edge[maxn << 1] ; int head[maxn],num = 0; inline vo

Codeforces G. Ant colony

题目描述: F. Ant colonytime limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard output Mole is hungry again. He found one ant colony, consisting of n ants, ordered in a row. Each ant i (1 ≤ i ≤ n) has a strength si.

Codeforces 739B Alyona and a tree (树上路径倍增及差分)

题目链接 Alyona and a tree 弄了好几个小时终于Accepted了,之后发现这个题是Div1的. 比较考验我思维的一道好题. 首先,做一遍DFS预处理出t[i][j]和d[i][j].t[i][j]表示从第i个节点到离他第2^j近的祖先,d[i][j]表示从i开始到t[i][j]的路径上的路径权值总和. 在第一次DFS的同时,对节点x进行定位(结果为dist(x, y)<=a(y))的离x最远的x的某个祖先,然后进行O(1)的差分. 第一次DFS完成后,做第二次DFS统计答案(统

codeforces 342E :Xenia and Tree

Description Xenia the programmer has a tree consisting of n nodes. We will consider the tree nodes indexed from 1 to n. We will also consider the first node to be initially painted red, and the other nodes — to be painted blue. The distance between t

【CodeForces】E. Xenia and Tree(分块 + LCA)

对于两个操作,对于操作1,每次储存要修改的点,直到存了sqrt(m)个点的时候进行更新,并将图重建一次(重新记录每个点到最近染色点的距离) 对于操作2,利用LCA求现在存着的点(也就是还没有更新到图上的点)和这个点的距离的最小值以及这个点在当前图中和最近的染色的那个点的距离. 话说LCA真是个好东西=  =!这几天补一补去 题解在这里:http://codeforces.com/blog/entry/8800 #include<cmath> #include<queue> #inc

codeforces 161 D. Distance in Tree(树形dp)

题目链接:http://codeforces.com/problemset/problem/161/D 题意:给出一个树,问树上点到点的距离为k的一共有几个. 一道简单的树形dp,算是一个基础题. 设dp[i][len]表示i为根距离为len的一共有几个点. 一般的树形dp都是先dfs然后再更新dp的值,注意按这样写就行了.而且一般的树形dp都是设dp[i][k]i为根,k为条件. void dfs(int u , int pre) { int len = vc[u].size(); dp[u]

Codeforces 763A. Timofey and a tree

A. Timofey and a tree 题意:给一棵树,要求判断是否存在一个点,删除这个点后,所有连通块内颜色一样.$N,C \le 10^5$ 想法:这个叫换根吧.先求出一个点合法即其儿子的子树内颜色一样,非该点子树的点颜色都一样.可以用DFS序解决. #include< cstdio > typedef long long ll; template inline void read(T&x) { x=0;bool f=0;char c=getchar(); while((c&l