zoukankan      html  css  js  c++  java
  • POJ 1987

    T_T为毛会这样子,我的写就是过不了,。。。。。。。

    其实这题不难,很容易想到吧,我一开始也想着用枚举这类方法,但复杂度实在不敢想,没想到,真的是用这种方法。。

    今天学了一个叫树的重心,可以使分治的子树点数大致相等,降低了递归的层次吧。。。

    嗯,这题的复杂度,怎么的也有o(n^2)以上,而且n=40000,竟然。。。。不敢细想了。。。。

    代码复制:http://blog.csdn.net/acm_cxlove/article/details/9222999

    我自己锉代码就算了T_T,搞不懂了。。。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #pragma comment(linker, "/STACK:1024000000,1024000000")   
    using namespace std;
    const int N = 40005;
    struct Edge{
        int v,next,w;
    }e[N<<1];
    int tot,start[N],n,m,k,del[N],ans=0;
    int size[N];
    void _add(int u,int v,int w){
        e[tot].v=v;e[tot].w=w;
        e[tot].next=start[u];start[u]=tot++;
    }
    void add(int u,int v,int w){
        _add(u,v,w);
        _add(v,u,w);
    }
    void cal(int u,int pre){
        size[u]=1;
        for(int i=start[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(v==pre||del[v]) continue;
            cal(v,u);
            size[u]+=size[v];
        }
    }
    int newroot,maxsize,totalsize;
    void dfs(int u,int pre){
        int mx=0,sum=1;
        for(int i=start[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(v==pre||del[v]) continue;
            dfs(v,u);
            mx=max(mx,size[v]);
            sum+=size[v];
        }
        mx=max(mx,totalsize-sum);
        if(mx<maxsize){
            maxsize=mx;
            newroot=u;
        }
    }
    int search(int r){
        newroot=-1;maxsize=1<<30;
        cal(r,-1);
        totalsize=size[r];
        dfs(r,-1);
        return newroot;
    }
    int dist[N],idx;
    vector<int>sub[N],all;
    void gao(int u,int pre){
        all.push_back(dist[u]);
        sub[idx].push_back(dist[u]);
        for(int i=start[u];i!=-1;i=e[i].next){
            int v=e[i].v,w=e[i].w;
            if(v==pre||del[v]) continue;
            dist[v]=dist[u]+w;
            gao(v,u);
        }
    }
    void solve(int root){
        root=search(root);
        del[root]=1;
        if(totalsize==1) return ;
        idx=0;all.clear();
        for(int i=start[root];i!=-1;i=e[i].next){
            int v=e[i].v,w=e[i].w;
            if(del[v]) continue;
            sub[idx].clear();
            dist[v]=w;
            gao(v,-1);
            sort(sub[idx].begin(),sub[idx].end());
            idx++;
        }
        for(int i=0;i<idx;i++){
            int pos;
            for(int j=0;j<sub[i].size();j++){
                pos=upper_bound(sub[i].begin(),sub[i].end(),k-sub[i][j])-sub[i].begin()-1;
                if(pos>j) ans-=pos-j;
            }
            pos=upper_bound(sub[i].begin(),sub[i].end(),k)-sub[i].begin()-1;
            if(pos>=0) ans+=pos+1;
        }
        sort(all.begin(),all.end());
        for(int i=0;i<all.size();i++){
            int pos=upper_bound(all.begin(),all.end(),k-all[i])-all.begin()-1;
            if(pos>i) ans+=pos-i;
        }
        for(int i=start[root];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(del[v]) continue;
            solve(v);
        }
    }
    int main(){
        tot=0;memset(start,-1,sizeof(start));
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++){
            int u,v,w;char str[5];
            scanf("%d%d%d%s",&u,&v,&w,str);
            add(u,v,w);
        }
        scanf("%d",&k);
        solve(1);
        printf("%d
    ",ans);
        return 0;
    }
    

      

  • 相关阅读:
    redis运维的一些知识点
    nginx 实现Web应用程序的负载均衡
    JQuery中常用方法备忘
    高效程序猿之 VS2010快速生成代码模板
    C# var 隐式类型 var 用法 特点
    HTML之打开/另存为/打印/刷新/查看原文件等按钮的代码
    js函数大全(2)
    js常用函数大全107个
    js键盘键值大全
    js键盘键值大全
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4331353.html
Copyright © 2011-2022 走看看