zoukankan      html  css  js  c++  java
  • 洛谷 P3806 【模板】点分治1

    洛谷 P3806 【模板】点分治1

    洛谷传送门

    题目描述

    给定一棵有 nn 个点的树,询问树上距离为 kk 的点对是否存在。

    输入格式

    第一行两个数 n,mn,m

    第 22 到第 nn 行,每行三个整数 u, v, wu,v,w,代表树上存在一条连接 uu 和 vv 边权为 ww 的路径。

    接下来 mm 行,每行一个整数 kk,代表一次询问。

    输出格式

    对于每次询问输出一行一个字符串代表答案,存在输出 AYE,否则输出 NAY


    题解:

    看起来像是POI波兰那边的题。

    算是点分治的模板?

    关于点分治的讲解,请看:

    详解点分治

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define N 10001
    #define re register 
    inline int read()
    {
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9'){
            if(c=='-')f=-1;
            c=getchar();
        }
        while(c>='0'&&c<='9'){
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        return x*f;
    }
    int n,m,query[101];
    int cnt=0,mp[N],size[N],root,tot=0,d[N],b[N],a[N];
    bool vis[N],ans[101];
    int to[N<<1],nxt[N<<1],head[N],val[N<<1];
    void add(int a,int b,int c)
    {
    	cnt++;
    	nxt[cnt]=head[a];
    	to[cnt]=b;
    	val[cnt]=c;
    	head[a]=cnt;
    }
    void getroot(int x,int fa,int total)
    {
    	size[x]=1;
    	mp[x]=0;
    	for(re int i=head[x];i;i=nxt[i])
    	{
    		int y=to[i];
    		if(y==fa||vis[y])
    			continue;
    		getroot(y,x,total);
    		size[x]+=size[y];
    		mp[x]=max(size[y],mp[x]);
    	}
    	mp[x]=max(mp[x],total-size[x]);
    	if(!root||mp[x]<mp[root])
    		root=x;
    }
    bool cmp(int x,int y)
    {
    	return d[x]<d[y];
    }
    void get_dis(int x,int fa,int dis,int from)
    {
    	a[++tot]=x;
    	d[x]=dis;
    	b[x]=from;
    	for(re int i=head[x];i;i=nxt[i])
    	{
    		int y=to[i];
    		if(y==fa||vis[y])
    			continue;
    		get_dis(y,x,dis+val[i],from);
    	}
    }
    void calc(int x)
    {
    	tot=0;
    	a[++tot]=x;
    	d[x]=0;
    	b[x]=x;
    	for(int i=head[x];i;i=nxt[i])
    	{
    		int y=to[i];
    		if(vis[y])
    			continue;
    		get_dis(y,x,val[i],y);
    	}
    	sort(a+1,a+tot+1,cmp);
    	for(int i=1;i<=m;i++)
    	{
    		int l=1,r=tot;
    		if(ans[i])
    			continue;
    		while(l<r)
    		{
    			if(d[a[l]]+d[a[r]]>query[i])
    				r--;
    			else if(d[a[l]]+d[a[r]]<query[i])
    				l++;
    			else if(b[a[l]]==b[a[r]])
    			{
    				if(d[a[r]]==d[a[r-1]])
    					r--;
    				else 
    					l++;
    			}
    			else
    			{
    				ans[i]=1;
    				break;
    			}
    		}
    	}
    }
    void dfz(int x)
    {
    	vis[x]=1;
    	calc(x);
    	for(re int i=head[x];i;i=nxt[i])
    	{
    		int y=to[i];
    		if(vis[y])
    			continue;
    		root=0;
    		getroot(y,0,size[y]);
    		dfz(root);
    	}
    }
    int main()
    {
    	n=read(),m=read();
    	for(re int i=1;i<n;i++)
    	{
    		int x,y,w;
    		x=read(),y=read(),w=read();
    		add(x,y,w);
    		add(y,x,w);
    	}
    	for(re int i=1;i<=m;i++)
    	{
    		query[i]=read();
    		if(!query[i])
    			ans[i]=1;
    	}
    	mp[0]=n;
    	getroot(1,0,n);
    	dfz(root);
    	for(re int i=1;i<=m;i++)
    		if(ans[i])
    			puts("AYE");
    		else
    			puts("NAY");
    	return 0;
    }
    
  • 相关阅读:
    linux驱动模板
    Matlab的安装
    级数模型
    多元思维
    一级指针和二级指针
    Biology 053: Visualization of Digestive Enzymes
    Biology 052: Digestion Experiment
    Biology 06: Metabolism and Nutrition
    线性回归之电力预测
    python之产生随机数
  • 原文地址:https://www.cnblogs.com/fusiwei/p/13822620.html
Copyright © 2011-2022 走看看