有个东西叫树的直径。。。
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;
}