zoukankan      html  css  js  c++  java
  • BZOJ1316: 树上的询问

    【传送门:BZOJ1316


    简要题意:

      给出一棵n个点的带边权有根树

      有q个询问,每个询问输入len,判断在树上是否存在长度为len的路径


    题解:

      直接点分治,用set保存链的长度就行了


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<set>
    #define Maxn 11000
    #define INF 1<<30
    using namespace std;
    struct node{int x,y,d,next;}a[Maxn*2];int len,last[Maxn];
    void ins(int x,int y,int c){a[++len]=(node){x,y,c,last[x]};last[x]=len;}
    int ms[Maxn],sum,tot[Maxn],rt;
    bool v[Maxn];
    set<int> S;
    void getrt(int x,int fa)
    {
        tot[x]=1;ms[x]=0;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y==fa||v[y]==true) continue;
            getrt(y,x);
            tot[x]+=tot[y];
            ms[x]=max(ms[x],tot[y]);
        }
        ms[x]=max(ms[x],sum-tot[x]);
        if(ms[x]<ms[rt]) rt=x;
    }
    int dep[Maxn],Q,q[Maxn];
    int p[Maxn];
    void cal(int x,int fa,int d)
    {
        for(int i=1;i<=Q;i++) if(S.find(q[i]-d)!=S.end()) p[i]=true;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y==fa||v[y]==true) continue;
            cal(y,x,d+a[k].d);
        }
    }
    void add(int x,int fa,int d)
    {
        S.insert(d);
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y==fa||v[y]==true) continue;
            add(y,x,d+a[k].d);
        }
    }
    void solve(int x)
    {
        v[x]=true;S.insert(0);
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(v[y]==true) continue;
            cal(y,x,a[k].d);
            add(y,x,a[k].d);
        }
        S.clear();
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(v[y]==true) continue;
            rt=0;sum=tot[y];getrt(y,x);
            solve(rt);
        }
    }
    int main()
    {
        int n;
        scanf("%d%d",&n,&Q);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<n;i++)
        {
            int x,y,c;
            scanf("%d%d%d",&x,&y,&c);
            ins(x,y,c);ins(y,x,c);
        }
        memset(v,false,sizeof(v));
        rt=0;sum=ms[rt]=n;getrt(1,0);
        memset(p,false,sizeof(p));
        for(int i=1;i<=Q;i++) scanf("%d",&q[i]);
        solve(rt);
        for(int i=1;i<=Q;i++)
        {
            if(p[i]==true||q[i]==0) printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }

     

  • 相关阅读:
    Delphi7 (第一天:类的编写)
    设计模式(二)Abstract Factory
    hdu 3335(最小路径覆盖)
    hdu 2236(最大匹配+枚举上下界)
    hdu 2819(二分匹配)
    hdu 3861(缩点+最小路径覆盖)
    hdu 2831(贪心)
    hdu 4296(贪心)
    hdu 2354(bfs求最短路)
    hdu 4313(类似于kruskal)
  • 原文地址:https://www.cnblogs.com/Never-mind/p/10154042.html
Copyright © 2011-2022 走看看