acdeam 1027 Path(树型DP)

题目链接: http://www.acdream.net/problem.php?id=1027

题意:给出一个n个节点的树,每条边的权值为1或者2。Q个询问,每个询问一个数L,问树中是否存在一个长度为L的链?
思路:若有长度为x的链,则必有长度为x-2的链。因此,求出树中长度为偶数的最长的链和长度为奇数的最长的链即可。
#include <iostream>

#include <cstdio>

#include <cstring>

#include <vector>

#define max(x,y) ((x)>(y)?(x):(y))

using namespace std;

 

struct node

{

    int v,dis,next;

 

    node(){}

    node(int _v,int _dis)

    {

        v=_v;

        dis=_dis;

    }

};

 

const int INF=1000000000;

const int MAX=100005;

vector<node> V[MAX];

int f[MAX][2],p[2];

int n,Q;

 

void DFS(int u,int pre)

{

    f[u][0]=0;

    f[u][1]=-INF;

    int i,v,dis,x,y;

    for(i=0;i<V[u].size();i++)

    {

        v=V[u][i].v;

        dis=V[u][i].dis;

        if(v==pre) continue;

        DFS(v,u);

        for(x=0;x<2;x++) for(y=0;y<2;y++)

        {

            p[(x+y+dis)&1]=max(p[(x+y+dis)&1],f[u][x]+f[v][y]+dis);

        }

        f[u][dis&1]=max(f[u][dis&1],f[v][0]+dis);

        f[u][(dis+1)&1]=max(f[u][(dis+1)&1],f[v][1]+dis);

    }

}

 

int main()

{

    while(scanf("%d%d",&n,&Q)!=-1)

    {

        int i,u,v,dis;

        for(i=1;i<=n;i++) V[i].clear();

        for(i=1;i<n;i++)

        {

            scanf("%d%d%d",&u,&v,&dis);

            V[u].push_back(node(v,dis));

            V[v].push_back(node(u,dis));

        }

        p[0]=p[1]=0;

        DFS(1,-1);

        while(Q--)

        {

            scanf("%d",&dis);

            if(dis<0||dis>p[dis&1]) puts("No");

            else puts("Yes");

        }

    }

    return 0;

}

  

你可能感兴趣的:(Path)