poj 1741 树的分治。。。。

poj 1741 树的分治。。。。

队友给推荐了这道题。做了两天。看了题解的大概思路,结合自己原来的思路搞了一晚上总算A了。
链接:http://poj.org/problem?id=1741
代码:
#include<stdio.h>
#include<stdlib.h>
#include <algorithm>
#include<vector>
#define ma 10010
using namespace std;
int n,k;
typedef struct nod
{
    int l,v;
}Node;
vector<Node> node[ma];
vector<int> len;
bool bu[ma];
int size,jude,sum;
int getsize(int x,int f)
{
    int sum=1;
    for(int i=0;i<node[x].size();i++)
    {
        int ans=node[x][i].l;
        if(bu[ans]&&ans!=f)
        {
            sum+=getsize(ans,x);
        }
    }
    return sum;
}
int getroot(int x,int f,int *root)
{
    int max=0,ss=1,temp;
    for(int i=0;i<node[x].size();i++)
    {
        int ans=node[x][i].l;
        if(bu[ans]&&ans!=f)
        {
            temp=getroot(ans,x,root);
            if(temp>max)max=temp;
            ss+=temp;
        }
    }
    if((size-ss)>max)max=size-ss;
    if(max<jude){jude=max;*root=x;}
    return ss;
}
void getd(int x,int f,int v)
{
    len.push_back(v);
    for(int i=0;i<node[x].size();i++)
    {
        int ans=node[x][i].l;
        if(bu[ans]&&ans!=f)
        {
            getd(ans,x,v+node[x][i].v);
        }
    }
}
int con(int x,int limit)
{
    len.clear();
    getd(x,x,0);
    sort(len.begin(),len.end());
    int ll=0;
    for(int l=0,r=len.size()-1;l<r;)
    {

        if(len[r]+len[l]<=k-2*limit)
        {
            ll+=(r-l);
            l++;
        }
        else r--;
    }
    return ll;
}
void ff(int x)
{
    sum+=con(x,0);
    bu[x]=false;
    for(int i=0;i<node[x].size();i++)
    {
        int ans=node[x][i].l;
        if(bu[ans])
        {
            int root;
            size=getsize(ans,ans);
            jude=size;
            sum-=con(ans,node[x][i].v);
            getroot(ans,ans,&root);
            ff(root);
        }
    }
}
int main()
{
    Node nn;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        if(!n&&!k)break;
        for(int i=1;i<=n;i++)bu[i]=true;
        for (int i=0; i<=n; i++)node[i].clear();
        for(int i=1;i<n;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            nn.l=b;nn.v=c;
            node[a].push_back(nn);
            nn.l=a;
            node[b].push_back(nn);
        }
        sum=0;
        int root;
        size=getsize(1,1);
        jude=size;
        getroot(1,1,&root);
        ff(root);
        printf("%d\n",sum);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值