【点分治】3365: [Usaco2004 Feb]Distance Statistics 路程统计

3365: [Usaco2004 Feb]Distance Statistics 路程统计


Description

在得知了自己农场的完整地图后(地图形式如前三题所述),约翰又有了新的问题.他提供
一个整数K(1≤K≤109),希望你输出有多少对农场之间的距离是不超过K的.(题意略坑 我说一下 m是没用的因为这是一颗树 每行的第四个字母也没用,其他和1468 tree一样)


Input

第1到I+M行:与前三题相同;
第M+2行:一个整数K.


Output

农场之间的距离不超过K的对数.


Sample Input

7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S
10


Sample Output

5


HINT

对于100%的数据,N ≤ 40000。


Solution

和bzoj 1468一样
只是要多读入一些没用的东西..

Code

#include
#include
#include
#include

#define maxn 400001

using namespace std;

struct edge{
    int to,lst,c;
}e[maxn*2];

int last[maxn],tot,son[maxn],n,f[maxn],root,d[maxn],deep[maxn],K,sum;

bool vis[maxn];

void getroot(int poi,int lst)
{
    son[poi]=1;f[poi]=0; 
    for(int i=last[poi];i;i=e[i].lst)
        if(e[i].to!=lst && !vis[e[i].to])
        {
            getroot(e[i].to,poi);
            son[poi]+=son[e[i].to];
            f[poi]=max(f[poi],son[e[i].to]);
        }
    f[poi]=max(f[poi],n-son[poi]);
    if(f[root]>f[poi])root=poi;
} 

void getdeep(int poi,int lst)
{
    deep[++deep[0]]=d[poi];
    for(int i=last[poi];i;i=e[i].lst)
        if(e[i].to!=lst && !vis[e[i].to])
        {
            d[e[i].to]=d[poi]+e[i].c;
            getdeep(e[i].to,poi);
        }
}

int getsum(int poi,int now)
{
    d[poi]=now;deep[0]=0;
    getdeep(poi,0);
    sort(1+deep,1+deep+deep[0]);
    int t=0,l,r;
    for(int l=1,r=deep[0];lif(deep[l]+deep[r]<=K)t+=r-l,l++;
        else r--;
    }
    return t;
}

void solve(int poi)
{
    vis[poi]=1;
    sum+=getsum(poi,0);
    for(int i=last[poi];i;i=e[i].lst)
        if(!vis[e[i].to])
        {
            sum-=getsum(e[i].to,e[i].c);
            n=son[e[i].to];
            root=0;
            getroot(e[i].to,poi);
            solve(root);
        }
}

void add(int u,int v,int c)
{
    e[++tot]=(edge){v,last[u],c};last[u]=tot;
    e[++tot]=(edge){u,last[v],c};last[v]=tot;
} 

int main() 
{
    int k,m;
    scanf("%d%d",&n,&m);
    for(int i=1;iint u,v,c;
        scanf("%d%d%d",&u,&v,&c);
        getchar();getchar();
        add(u,v,c);
    }
    f[root]=100000;
    scanf("%d",&K);
    getroot(1,0);
    solve(root);
    printf("%d",sum);
    return 0;
}

你可能感兴趣的:(点分治)