采矿(oremine)题解

题目描述

作为一名刚拿到“苏联采矿车驾驶证”的司机来说,上战场采矿是一个很大的挑战。战场的形势复杂多变(最主要的原因是一不小心就会被恐怖机器人钻),但是这份工作丰厚的薪水还是使得苏联人民对之趋之若鹜。

现在你成为了一名光荣的矿车司机。交给你的任务是去采一片区域的矿。这片区域有N个矿点,矿点之间有N-1条长度为1的公路相连接。保证这些矿点两两都是可以通过公路到达的。你的矿车的油箱比较小,只能装M升柴油,而每行进长度为1的路程,就要消耗1升柴油。也就是说你只能行进M单位距离。为了简便,每个矿点的矿都是1个单位,并且当矿车驶过,矿就会被采完,第二次经过的时候就不会再有收益了。

你可以在任何一个矿点开始和结束采矿。

现在你想知道,你最多能采到多少单位的矿。

输入

第1行为两个整数N,M,意义上述。

第2行-第N行,每行两个整数u,v,表示在矿点u和矿点v之间有一条公路。

输出

一个整数,表示最多能采到多少矿。

样例输入

7 6
1 2
2 3
2 5
5 6
5 7
4 5

样例输出

5

提示

【数据范围】

30% :N<=200

50% :N<=20000

100%:N<=500000 M<=1000000 u!=v1<=u<=N1<=v<=N

想法

  • 裸的最长链。。。

算法

  • 见代码

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define MAXN 500005
using namespace std;
int n,m,x,y,head[MAXN],tot,depth[MAXN],ans,q[MAXN];
struct Node
{
    int u,v,next;
}edge[MAXN<<1];
inline void addedge(int u,int v)
{
    edge[tot].u=u,edge[tot].v=v,edge[tot].next=head[u],head[u]=tot++;
}
inline void add(int u,int v)
{
    addedge(u,v);
    addedge(v,u);
}
inline int bfs(int x)
{
    memset(depth,0,sizeof(depth));
    depth[x]=1;
    int l=1,r=2;
    q[1]=x;
    while(lint p=q[l++];
        for (int i=head[p];i!=-1;i=edge[i].next)
            if(!depth[edge[i].v])
            {
                depth[edge[i].v]=depth[p]+1;
                q[r++]=edge[i].v;
            }
    }
    return q[r-1];
}
int main()
{
    //freopen("oremine.in","r",stdin);
    //freopen("oremine.out","w",stdout);
    scanf("%d%d",&n,&m);
    memset(head,-1,sizeof(head));
    for (int i=1;i"%d%d",&x,&y);
        add(x,y);
    }
    ans=depth[bfs(bfs(1))]-1;
    printf("%d\n",min(n,mm+1:(m+ans)/2+1));
    return 0;
}

你可能感兴趣的:(图论,题解,最长链)