当前位置:编程学习 > C/C++ >>

Croc Champ 2013 - Round 2 题解

题目链接:

擒贼先擒王,每次赛后总结CF的题,我都喜欢先搞E题,而且E题一般是我最爱的数据结构题,搞起来特爽

E题:给你一棵树,求满足距离之和<=L 且 路径上的权值之和<= w的点对数量。。。

 

方法是点的分治,具体参考漆子超的论文,分治算法在树的路径中的应用,论文里面已经讲了很详细了

会了poj 1741的话,其实这道题就是多了一个限制,还是排序,扫描,不过在求的时候需要用树状数组维护一下,其实很简单,不过我还是调试了很久,,,,,代码能力与思维能力都需要精雕细琢啊。

在求一个二元组序列有多少对满足条件时卡了很久,看大神们都是加了一个0 0进去,我就是不想加,于是越写越烦,不是少算就是多算,最后冷静下来重新想了想,那还是先算成两倍的吧

我的那个calc函数略挫,,,,

poj 1741


[cpp]
#include<cstdio>  
#include<cstring>  
#include<vector>  
#include<algorithm>  
using namespace std; 
const int MAX_N = 100010; 
struct Edge{ 
    int b , w; 
    Edge() {} 
    Edge(int b,int w): b(b),w(w){ 
    } 
}; 
#define Tr(it,x) for(vector<Edge>::iterator it = x.begin(); it!=x.end();it++)  
vector<Edge> edge[MAX_N]; 
int N , K; 
int size[MAX_N]  ; 
int opt[MAX_N]; 
bool del[MAX_N] ; 
long long  Ans ; 
vector<int>  tnode; 
void Dfs(int u,int fa) 

    tnode.push_back(u); 
    opt[u] = 0; 
    size[u] = 1; 
    Tr(it,edge[u]) 
    { 
        int v = it->b; 
        if(!del[v] && v!=fa){ 
            Dfs(v , u); 
            opt[u] = max(opt[u],size[v]); 
            size[u] += size[v];  
        } 
    } 

int Find(int u) // find the centre of gravity  

    Dfs(u,-1); 
    int who = -1 , mx = MAX_N; 
    for(vector<int>::iterator it = tnode.begin(); it != tnode.end(); it++) 
    { 
        opt[*it] = max(opt[*it],size[u]-size[*it]); 
        if(mx > opt[*it]) { 
            mx = opt[*it]; 
            who = *it; 
        } 
    } 
    return who; 

vector<int> all , ch[MAX_N]; 
void Get_dis(int u,int fa,int len,vector<int> &ch) 

    ch.push_back(len); 
    all.push_back(len); 
    Tr(it,edge[u]) 
    { 
        if(it->b!=fa && !del[it->b]) { 
            Get_dis(it->b,u,len+it->w,ch); 
        } 
    } 

long long calc(vector<int> dist)  

    long long ans  = 0; 
    int pt = 0 , sz = dist.size(); 
    sort(dist.begin(),dist.end()); 
    for(int i = 0,j = sz - 1;i <= j;i++)  
    { 
        while(i <= j && dist[i] + dist[j] > K) { 
            j--; 
        } 
        if(i < j) ans += j - i; 
    } 
    return ans; 

void Solve(int u) 

    tnode.clear(); 
    u = Find(u); // the gravity center   
    all.clear(); // all of the distances  
    int nch = 0; // count of sons   
    all.push_back(0); 
    Tr(it,edge[u]) 
    { 
        ch[nch].clear();  
        if(!del[it->b]) Get_dis(it->b,u,it->w,ch[nch++]); 
    }    
    Ans += calc(all); 
    for(int i = 0; i < nch; i++)  Ans -= calc(ch[i]);     
 
    del[u] = true; 
    Tr(it,edge[u]) 
        if(!del[it->b])  Solve(it->b); 

int main() 

    int a,b,w; 
    while(scanf("%d%d",&N,&K),N||K) 
    { 
         for(int i = 1; i <= N; i++) edge[i].clear(),del[i]=false; 
         for(int i = 1; i < N; i++) 
         { 
             scanf("%d%d%d",&a,&b,&w); 
             edge[a].push_back(Edge(b,w)); 
             edge[b].push_back(Edge(a,w)); 
         } 
         Ans = 0; 
         Solve(1); 
         printf("%I64d\n",Ans); 
    } 
    return 0; 

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int MAX_N = 100010;
struct Edge{
 int b , w;
 Edge() {}
 Edge(int b,int w): b(b),w(w){
 }
};
#define Tr(it,x) for(vector<Edge>::iterator it = x.begin(); it!=x.end();it++)
vector<Edge> edge[MAX_N];
int N , K;
int size[MAX_N]  ;
int opt[MAX_N];
bool del[MAX_N] ;
long long  Ans ;
vector<int>  tnode;
void Dfs(int u,int fa)
{
 tnode.push_back(u);
 opt[u] = 0;
 size[u] = 1;
 Tr(it,edge[u])
 {
  int v = it->b;
  if(!del[v] && v!=fa){
   Dfs(v , u);
   opt[u] = max(opt[u],size[v]);
   size[u] += size[v]; 
  }
 }
}
int Find(int u) // find the centre of gravity
{
 Dfs(

补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,