程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> poj 1741 Tree 樹的分治

poj 1741 Tree 樹的分治

編輯:C++入門知識

解法論文中有,就是把路徑分成經過樹根,和不經過樹根兩類,每次處理經過樹根的,然後剩下的子樹部分可以遞歸處理,如果每次選取樹的重心,那麼可以保證最多遞歸logn層。經過樹根的先排序,然後O(n)的復雜度就能算出,那麼每層的復雜度nlogn,最多遞歸logn層,總復雜度nlogn^2

 
#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <algorithm>  
using namespace std;  
const int maxn=1e4+9;  
int head[maxn],lon;  
bool use[maxn];  
int a[maxn],d[maxn],top,son[maxn];  
int ans,n,m,mm;  
struct  
{  
    int next,to,w;  
}e[maxn<<1];  
  
void edgeini()  
{  
    memset(head,-1,sizeof(head));  
    lon=-1;  
}  
void edgemake(int from,int to,int w)  
{  
    e[++lon].to=to;  
    e[lon].w=w;  
    e[lon].next=head[from];  
    head[from]=lon;  
}  
int maxson[maxn];  
int dp(int t,int from)  
{  
    int now,tmp=1e5,ans;  
    son[t]=maxson[t]=0;  
    for(int k=head[t];k!=-1;k=e[k].next)  
    {  
        int u=e[k].to;  
        if(use[u]||u==from) continue;  
        now=dp(u,t);  
        if(maxson[now]<tmp)  
        {  
            tmp=maxson[now];  
            ans=now;  
        }  
        son[t]+=son[u];  
        maxson[t]=max(maxson[t],son[u]);  
    }  
    son[t]++;  
    maxson[t]=max(maxson[t],mm-son[t]);  
    if(maxson[t]<tmp) ans=t;  
    return ans;  
}  
  
void dfs(int t,int from)  
{  
    a[++top]=d[t];  
    son[t]=0;  
    for(int k=head[t],u;k!=-1;k=e[k].next)  
    {  
        u=e[k].to;  
        if(use[u]||u==from) continue;  
        d[u]=d[t]+e[k].w;  
        dfs(u,t);  
        son[t]+=son[u];  
    }  
    son[t]++;  
}  
  
int cal(int l,int r)  
{  
    int ret=0,now=r;  
    for(int i=l;i<=now;i++)  
    {  
        while(now>i&&a[i]+a[now]>m) now--;  
        ret+=now-i;  
    }  
    return ret;  
}  
  
void solve(int t)  
{  
    int now=dp(t,0);  
    d[now]=top=0;  
    use[now]=1;  
    dfs(now,0);  
    int ret=0,tmp=2;  
    for(int k=head[now];k!=-1;k=e[k].next)  
    {  
        int u=e[k].to;  
        if(use[u]) continue;  
        sort(a+tmp,a+tmp+son[u]);  
        ret+=cal(tmp,tmp+son[u]-1);  
        tmp+=son[u];  
    }  
    sort(a+1,a+tmp);  
    ans+=cal(1,tmp-1)-ret;  
//    printf("%d %d\n",now,ans);  
    for(int k=head[now];k!=-1;k=e[k].next)  
    {  
        int u=e[k].to;  
        if(use[u]||son[u]==1) continue;  
        mm=son[u];  
        solve(u);  
    }  
}  
  
int main()  
{  
//    freopen("in.txt","r",stdin);  
    while(scanf("%d %d",&n,&m),n&&m)  
    {  
        edgeini();  
        for(int i=1,from,to,w;i<n;i++)  
        {  
            scanf("%d %d %d",&from,&to,&w);  
            edgemake(from,to,w);  
            edgemake(to,from,w);  
        }  
        memset(use,0,sizeof(use));  
        ans=0;  
        mm=n;  
        solve(1);  
        cout<<ans<<endl;  
    }  
    return 0;  
}  

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved