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

崆若的水题之--赛跑的乌龟

时间:2015-05-13 19:19:54      阅读:117      评论:0      收藏:0      [点我收藏+]

标签:

因为想知道到底哪只乌龟跑的比兔子都快,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

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