标签:
因为想知道到底哪只乌龟跑的比兔子都快,Kong_Ruo在决定举行一场乌龟赛跑,场地有N座城市,是通过道路相连组成了一个N-1条边的无向无环图。每条边由ai连到bi,距离为ci。Kong_Rup决定选取两个城市分别为起点和终点,举行比赛。比赛时按这两个城市间的最短距离进行比赛。Kong_Ruo想选出一条尽量长的路径,但由于资金限制,路径长最多不能超过k。你能帮帮他吗?
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<ctime> using namespace std; const int maxn=30010; struct Node { Node* ch[2]; int r,v; }nodes[maxn],*null=new Node(),*S=null; queue<Node*> Q; Node* newnode() { Node* o=Q.front(); Q.pop(); return o; } void del(Node* &o) { Q.push(o); o=null; } void rotate(Node* &o,int d) { Node* k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o; o=k; } void insert(Node* &o,int v) { if(o==null) { o=newnode(); o->r=rand(); o->v=v; o->ch[0]=o->ch[1]=null; } else { int d=v<o->v?0:1; insert(o->ch[d],v); if(o->ch[d]->r>o->r) rotate(o,d^1); } } int find(Node* &o,int v) { if(o==null) return 0; int d=v<o->v?0:1; if(o->v==v) return v; else if(!d) return find(o->ch[0],v); else return max(o->v,find(o->ch[1],v)); } void clean(Node* &o) { if(o==null) return; clean(o->ch[0]);clean(o->ch[1]); del(o); } void print(Node* &o) { if(o==null) return; print(o->ch[0]); printf("%d ",o->v); print(o->ch[1]); } int first[maxn],to[maxn*2],next[maxn*2],d[maxn*2]; int n,m=1,k; void AddEdge(int a,int b,int c) { to[m]=b; d[m]=c; next[m]=first[a]; first[a]=m++; } int siz,root,f[maxn],s[maxn],done[maxn]; void findroot(int x,int fa) { int maxs=0; s[x]=1; for(int i=first[x];i;i=next[i]) if(to[i]!=fa&&!done[to[i]]) { findroot(to[i],x); s[x]+=s[to[i]]; maxs=max(maxs,s[to[i]]); } f[x]=max(siz-s[x],maxs); if(f[x]<f[root]) root=x; } int ans,A[maxn],tt=0; void dfs(int x,int fa,int dis) { s[x]=1; A[tt++]=dis; for(int i=first[x];i;i=next[i]) if(!done[to[i]]&&to[i]!=fa) { dfs(to[i],x,dis+d[i]); s[x]+=s[to[i]]; } } int tott; void solve(int x) { done[x]=1; insert(S,0); for(int i=first[x];i;i=next[i]) if(!done[to[i]]) { tt=0; dfs(to[i],x,d[i]); for(int j=0;j<tt&&A[j]<=k;j++) ans=max(ans,find(S,k-A[j])+A[j]); for(int j=0;j<tt;j++) insert(S,A[j]); } clean(S); for(int i=first[x];i;i=next[i]) if(!done[to[i]]) { dfs(to[i],x,0); siz=f[0]=s[to[i]]; findroot(to[i],root=0); solve(root); } } int main() { for(int i=0;i<maxn;i++) Q.push(&nodes[i]); int a,b,c; scanf("%d%d",&n,&k); for(int i=1;i<n;i++) { scanf("%d%d%d",&a,&b,&c); AddEdge(a,b,c); AddEdge(b,a,c); } f[0]=siz=n; findroot(1,root=0); solve(root); printf("%d\n",ans); return 0; }
输入
第一行为两个正整数N,k,表示N个城市,最长距离为K。
接下来N-1行为ai,bi,ci,表示有一条边从ai到bi,距离为ci。
输出
输出路径在小于等于k的情况下的最长长度。
输入示例
5 7
1 2 3
1 3 4
4 5 7
4 2 2
输出示例
7
标签:
原文地址:http://www.cnblogs.com/Kong-Ruo/p/4501220.html