1. 程式人生 > >Lady CA and the graph(HDU-5664)

Lady CA and the graph(HDU-5664)

轉化 sed als pri 通道 深搜 clu same \n

題目描述:

Lady CA has a tree with n points numbered 1,2,...,n, and each edge has its weight. The unique route connecting two points is called a chain, and the length of a chain equals the sum value of the weights of the edges passed.

The point number m is called the root. Lady CA defines a special kind of chain called folded chain, the chain connecting the points numbered x,y(x≠y)

is called a folded chain, if and only if the chain connecting the point numbered x and the root doesn‘t pass the point numbered y, and the chain connecting the point numbered y and the root doesn‘t pass the point numbered x.

Lady CA wants to find the length of the kth longest folded chain. Notice that the chain connecting the points numbered x,y

and the chain connecting the points numbered y,x are the same.

輸入

The first line contains an integer T(1≤T≤3)——The number of the test cases. For each test case:
The first line contains three integers n(2≤n≤50,000),m(1≤m≤n),k(1≤k≤n×(n?1)2). Between each two adjacent integers there is a white space separated.

The second line to the nth line describes the n?1 edges in the graph. Each line contains three integers u,v(1≤u,v≤n,u≠v),w(1≤w≤10,000), which means there is an edge which has a weight w connecting the points numbered u,v. Between each two adjacent integers there is a white space separated.

輸出

For each test case, the only line contains the only integer that is the length of the kth longest folded chain. If the kth longest folded chain doesn‘t exist, print NO.

樣例輸入

思路:

做這題首先需要知道的思想就是:求一個第k大的值能夠轉化為二分答案求最大的不小於它的數大於等於k個的值(這話有點繞但十分重要),它打開我們解這道題的一個通道。

接下來就是求樹中大於等於這個值的路徑數了,這個自然能想到點分治求解,做法和之前我寫的一道題一樣(POJ-1741),但是接下來就要考慮到限制條件了,就是路徑的兩端都不能是另一端的祖先,同樣要將其在答案中減去。那麽就只要深搜掃一遍樹,對於每個節點,算出祖先中距離自己大於當前二分值的祖先個數即可。至於如何快速計算這個數,用一個樹狀數組即可,下標存長度,不過數組開不下,那麽就先把樹掃一遍,記下每個長度,再將其離散化即可

還有一個要註意的就是由於要二分答案,不能每次都把點分治的操作一模一樣地做一遍,所以就把它給預處理出來,包括操作順序,以及每個重心後的子樹的重心等,還有每個點到重心的距離,存在兩個vector裏,這樣就能直接訪問了!

綜合以上的思路,最終便能求解,復雜度約為nlog3n,代碼有點長,要耐心打,仔細調

代碼

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define FOR(i,l,r) for(int i=(int)l;i<=(int)r;i++)
#define DOR(i,r,l) for(int i=(int)r;i>=(int)l;i--)
#define loop(i,n) for(int i=0;i<(int)n;i++)
#define ll long long
#define sf scanf
#define pf printf
#define mms(a,x) memset(a,x,sizeof a)
#define lowbit(x) (x)&-(x)
using namespace std;
const int N=50005;
int n,m;ll k;
struct Graph{
    int tot,to[N<<1],nxt[N<<1],len[N<<1],head[N];
    void add(int x,int y,int z){tot++;to[tot]=y;len[tot]=z;nxt[tot]=head[x];head[x]=tot;}
    void clear(){mms(head,-1),tot=0;}
    #define EOR(i,x) for(int i=G.head[x];i!=-1;i=G.nxt[i])
}G;
vector<int>v[N*10],rt_v[N];

bool vis[N];
int RT,dfn,center,t_sz,sz[N],mx[N];
void get_center(int x,int f){
    sz[x]=1,mx[x]=0;
    EOR(i,x){
        int v=G.to[i];
        if(v==f||vis[v])continue;
        get_center(v,x);
        sz[x]+=sz[v];
        mx[x]=max(mx[x],sz[v]);
    }
    mx[x]=max(mx[x],t_sz-sz[x]);
    if(!center||mx[center]>mx[x])center=x;
}
void dis_init(int x,int f,int dis){
    v[dfn].push_back(dis);
    EOR(i,x){
        int v=G.to[i];
        if(v==f||vis[v])continue;
        dis_init(v,x,dis+G.len[i]);
    }
}
void son_init(int x,int f,int dis){
    dfn++;
    dis_init(x,f,dis);
    sort(v[dfn].begin(),v[dfn].end());
}
void dfs_init(int x){
    vis[x]=1;
    son_init(x,0,0);
    EOR(i,x){
        int v=G.to[i];
        if(vis[v])continue;
        son_init(v,x,G.len[i]);
        center=0,t_sz=sz[v];
        get_center(v,x);
        rt_v[x].push_back(center);
        dfs_init(center);
    }
}
void tree_init(){
    FOR(i,1,n)rt_v[i].clear();
    FOR(i,1,10*n)v[i].clear();
    mms(vis,0);
    dfn=0;
    center=0,t_sz=n;
    get_center(1,0);
    RT=center;
    dfs_init(center);
}

int id,sum,arr[N<<1];
struct Binary_Indexed_Tree{
    int c[N<<1];
    void update(int x,int val){while(x<=arr[0])c[x]+=val,x+=lowbit(x);}
    int sum(int x){int ret=0;while(x){ret+=c[x];x-=lowbit(x);}return ret;}
    void clear(){mms(c,0);}
}Tr;
int calc(int val){
    int ret=0,j=v[++id].size()-1,i=0;
    while(i<j){
        while(i<j&&v[id][i]+v[id][j]<val)i++;
        ret+=j-i,j--;
    }
    return ret;
}
void dfs(int x,int val){
    sum+=calc(val);
    loop(i,rt_v[x].size()){
        int v=rt_v[x][i];
        sum-=calc(val);
        dfs(v,val);
    }
}
void dis_dfs(int x,int f,int dis,int val){
    arr[++arr[0]]=dis,arr[++arr[0]]=dis-val;
    EOR(i,x){
        int v=G.to[i];
        if(v==f)continue;
        dis_dfs(v,x,dis+G.len[i],val);
    }
}
void update_dfs(int x,int f,int dis,int val){
    int pos1=lower_bound(arr+1,arr+arr[0]+1,dis)-arr;
    int pos2=lower_bound(arr+1,arr+arr[0]+1,dis-val)-arr;
    sum-=Tr.sum(pos2),Tr.update(pos1,1);
    EOR(i,x){
        int v=G.to[i];
        if(v==f)continue;
        update_dfs(v,x,dis+G.len[i],val);
    }
    Tr.update(pos1,-1);
}
int check(int x){
    sum=0,dfs(RT,x);
    id=arr[0]=0,dis_dfs(m,0,0,x);
    sort(arr+1,arr+arr[0]+1);
    arr[0]=unique(arr+1,arr+arr[0]+1)-arr-1;
    update_dfs(m,0,0,x);
    return sum;
}
void init(){
    G.clear();
}
int main(){
    int T;
    sf("%d",&T);
    while(T--){
        int Mx=0;
        init();
        sf("%d%d%lld",&n,&m,&k);
        FOR(i,1,n-1){
            int x,y,z;
            sf("%d%d%d",&x,&y,&z);
            G.add(x,y,z),G.add(y,x,z);
            Mx=max(Mx,z);
        }
        tree_init();
        int l=0,r=n*Mx,ans=-1;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid)>=k)ans=mid,l=mid+1;
            else r=mid-1;
        }
        if(ans!=-1)pf("%d\n",ans);
        else puts("NO");
    }
    return 0;
}

Lady CA and the graph(HDU-5664)