树的直径

有个东西叫树的直径。。。

1.树上面最长简单路(无环),就是树的直径问题

2.两遍dfs即可

分析:一开始任取一个点u进行搜索查找出距离点u最远距离的点v和长度

      第二次dfs则从第一次中的v找出距离点v最远距离的点的路径长度



有点类似于树形dp的感觉。。

poj  1985  Cow Marathon

这题就是裸的求树的直径吧  就是找出树中最长链的长度

就是这题没给数据范围。。。莫名其妙的。。。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>

#define eps 1e-8
#define op operator
#define MOD  10009
#define MAXN  500100
#define INF 0x7fffffff

#define FOR(i,a,b)  for(int i=a;i<=b;i++)
#define FOV(i,a,b)  for(int i=a;i>=b;i--)
#define REP(i,a,b)  for(int i=a;i<b;i++)
#define REV(i,a,b)  for(int i=a-1;i>=b;i--)
#define MEM(a,x)    memset(a,x,sizeof a)
#define ll __int64

using namespace std;

int head[MAXN],dis[MAXN];

struct node
{
    int to;//边的终点
    int next;//下一条边的编号
    int dis;//边的长度
};
node edge[10000000];

int num;

void addedge(int u,int v,int w)
{
    edge[num].to=v;
    edge[num].dis=w;
    edge[num].next=head[u];
    head[u]=num++;
}

void dfs(int f,int u,int d)
{
    dis[u]=d;
    for(int i=head[u];i!=-1;i=edge[i].next)
        if(edge[i].to!=f)//排除重复计算
            dfs(u,edge[i].to,d+edge[i].dis);
}

int main()
{
//freopen("ceshi.txt","r",stdin);
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        MEM(head,-1);
        num=0;
        while(m--)
        {
            int u,v,w;
            char s[20];
            scanf("%d%d%d%s",&u,&v,&w,s);
            addedge(u,v,w);
            addedge(v,u,w);
        }
        dfs(0,1,0);
        int mx=-1; int tag;
        for(int i=1;i<=n;i++)
            if(dis[i]>mx)
        {
            mx=dis[i]; tag=i;
        }
        dfs(0,tag,0);
        mx=-1;
        for(int i=1;i<=n;i++)
            if(dis[i]>mx)
                mx=dis[i];
        printf("%d\n",mx);
    }
    return 0;
}


hdu 4607
题意就是n个点  n-1条边  边的长度都为1   
有m个询问   询问走过k个节点 最少走多少距离
求出树中最长的路径长度mx(即覆盖mx+1个节点)  
如果k<=mx+1  则直接可以在树中最长链上走 没有重复走过的距离
如果k>mx+1   则除了走完最长链还要走过最长链上节点的子节点  就会有重复的距离
需要多走的节点数为 k-(mx+1)  则要多走的距离为( k-(mx+1))*2  所以此时总距离为 mx+ ( k-(mx+1) )*2 
代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>

#define eps 1e-8
#define op operator
#define MOD  10009
#define MAXN  100100
#define INF 0x7fffffff

#define FOR(i,a,b)  for(int i=a;i<=b;i++)
#define FOV(i,a,b)  for(int i=a;i>=b;i--)
#define REP(i,a,b)  for(int i=a;i<b;i++)
#define REV(i,a,b)  for(int i=a-1;i>=b;i--)
#define MEM(a,x)    memset(a,x,sizeof a)
#define ll __int64

using namespace std;

int n,m;
int num;
int head[100100];
int dis[100100];


struct node
{
    int to,next,dis;
};
node edge[200100];//同一条边算了两次。。。

void addedge(int u,int v,int d)
{
    edge[num].to=v;
    edge[num].dis=d;
    edge[num].next=head[u];
    head[u]=num++;
}

void dfs(int f,int u,int d)
{
    dis[u]=d;
    for(int i=head[u];i!=-1;i=edge[i].next)
        if(edge[i].to!=f)
            dfs(u,edge[i].to,d+edge[i].dis);
}

int main()
{
//freopen("ceshi.txt","r",stdin);
    int tc;
    scanf("%d",&tc);
    while(tc--)
    {
        MEM(head,-1);
        scanf("%d%d",&n,&m);
        num=0;
        for(int i=0;i<n-1;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v,1);
            addedge(v,u,1);
        }
        int mx=-1,tag;
        dfs(0,1,0);
        for(int i=1;i<=n;i++)
            if(mx<dis[i])
        {
            mx=dis[i]; tag=i;
        }
        dfs(0,tag,0);
        mx=-1;
        for(int i=1;i<=n;i++)
            if(mx<dis[i])
                mx=dis[i];
        for(int i=0;i<m;i++)
        {
            int k;
            scanf("%d",&k);//k代表走过的节点数
            if(k<=(mx+1))
                printf("%d\n",k-1);
            else
                printf("%d\n",mx+(k-(mx+1))*2);
        }
    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值