码迷,mamicode.com
首页 > 其他好文 > 详细

poj2114 寻找树上存在长度为k点对,树上的分治

时间:2015-10-05 22:01:14      阅读:277      评论:0      收藏:0      [点我收藏+]

标签:

寻找树上存在长度为k点对,树上的分治  代码和  这个  差不多 ,改一下判断的就好

技术分享
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <string.h>
using namespace std;
const int maxn=10004;
int H[maxn],nx[maxn*2],to[maxn*2],numofE,dist[maxn*2];
void add(int u,int v, int d)
{
    numofE++;
    dist[numofE]=d;
    to[numofE]=v;
    nx[numofE]=H[u];
    H[u]=numofE;
}
void init(int N){
  numofE=0;
  memset(H,0,sizeof(H));
}
int ans;
int subnum[maxn],Q[maxn+10],fa[maxn];
bool center[maxn];
int N,K;
int searchroot(int cur)
{
    int rear=0,root=cur;
    Q[rear++]=cur;fa[cur]=0;
    for(int i=0; i<rear; i++)
    {
        int x=Q[i];
        for(int j=H[x]; j; j=nx[j])
            if(to[j]!=fa[x]&&center[to[j]]==false)
            Q[rear++]=to[j],fa[to[j]]=x;
    }
    int MIN=maxn;
    for(int i=rear-1; i>=0; i--)
    {
        int x=Q[i];
        subnum[x]=1;
        int MA=0;
        for(int j=H[x]; j ; j=nx[j])
            if(to[j]!=fa[x]&&center[to[j]]==false)
            MA=max(MA,subnum[to[j]]),subnum[ x ]+=subnum[ to[j] ];
        MA=max(MA,rear-subnum[x]);
        if(MIN>MA)MIN=MA,root=x;
    }
    return root;
}
int P[maxn];
int count_pair(int s, int t)
{
    int ge=0,l=t,r=t;
    for(int i=s; i<t; i++)
    {
         while(r>s&&P[i]+P[r-1]>K)r--;
         while(l>s&&P[i]+P[l-1]>=K)l--;
         if(i>=l&&i<r)ge+=r-l-1;
         else ge+=r-l;
    }
    return ge/2;
}
void updateedg(int s, int cur, int d)
{
    int rear=0;
    Q[rear++]=cur;fa[cur]=0;P[s]=d;
    for(int i=0; i<rear; i++)
    {
        int x=Q[i];
        for(int j=H[x];j; j=nx[j])
        {
            int tto=to[j];
            if(center[tto]||tto==fa[x])continue;
            P[s+rear]=P[s+i]+dist[j],Q[rear++]=tto,fa[tto]=x;
        }
    }
    sort(P+s,P+s+rear);
}
int dfs(int s, int cur, int d)
{
    int root,tot=1;
    root=searchroot(cur);
    center[root]=true;
    for(int i=H[root]; i ;i=nx[i])
    {
        int tto=to[i];
        if(center[tto])continue;
        int n=dfs(s+tot,tto,dist[i]);
        if(ans>0){
            center[root]=false;return 0;
        }
        ans-=count_pair(s+tot,s+tot+n);
        tot+=n;
    }
    P[s]=0;
    sort(P+s,P+s+tot);
    ans+=count_pair(s,s+tot);
    if(ans>0){
        center[root]=false;return 0;
    }
    center[root]=false;
    updateedg(s,cur,d);
    return tot;
}
int main()
{
      for(;;)
      {
          scanf("%d",&N); if(N==0)break;
        init(N);
        for(int i=1;i<=N; i++)
            {

                 int d;
                 for(;;)
                {
                    scanf("%d",&d); if(d==0)break;
                 int c; scanf("%d",&c);
                 add(i,d,c);add(d,i,c);
                }
            }
        for(;;)
        {
            scanf("%d",&K);if(K==0)break;
            ans=0;
            dfs(0,1,0);
            if(ans>0)
            puts("AYE");
            else puts("NAY");
         }
         puts(".");
    }
    return 0;
}
/*
6
2 1 3 1 4 1 0
0
5 1 6 1 0
0
0
0
2
*/
View Code

 

poj2114 寻找树上存在长度为k点对,树上的分治

标签:

原文地址:http://www.cnblogs.com/Opaser/p/4856227.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!