pku1985 Cow Marathon(树上的最远简单路)
//方法1,1141MS:
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
#define MAXN 40001
struct ENode
{
int adv,dis;
};
vector<ENode> adjlist[MAXN];
int N,ans;
bool visited[MAXN];
int dfs(int i)
{//基于深度优先搜树(是一棵二叉树),不断比较左、右、相加谁大。。。
visited[i]=true;
int lv=-1,rv=-1;
for(vector<ENode>::size_type j=0;j<adjlist[i].size();j++)
{
int v=adjlist[i][j].adv;
if(!visited[v])
{
int tmp=dfs(v)+adjlist[i][j].dis;
if(tmp>lv)
{
rv=lv;
lv=tmp;
/*
此时这里包含两种情况之一。
1.rv依然等于-1,表示这个tmp是左儿子返回值+adjlist[i][j].dis,而右儿子还未访问
2.否则,是右儿子值返回值>左儿子返回值的情况,此时相当于交换了左右返回的值+adjlist[i][j].dis,
保证了左返回值+adjlist[i][j].dis是较大的,好让dfs返回的是lv
*/
}
else if(tmp>rv)
{//表示右儿子也访问完毕
rv=tmp;
}
}
}
if(lv==-1) return 0;
if(rv==-1)//表示只有左儿子,则要和ans比较谁大
{
if(lv>ans) ans=lv;
}
else
{
if(lv+rv>ans) ans=lv+rv;
}
return lv;
}
int main()
{
int M,i,j,d;
ENode e;
char ch;
while(scanf("%d %d",&N,&M)!=EOF)
{
getchar();
memset(visited,false,sizeof(*visited)*(N+1));
while(M--)
{
scanf("%d %d %d %c",&i,&j,&d,&ch);
e.adv=j;
e.dis=d;
adjlist[i].push_back(e);
e.adv=i;
adjlist[j].push_back(e);
getchar();
}
ans=-1;
dfs(1);
printf("%d\n",ans);
}
return 0;
}
//****************************************************************************
树的直径(Diameter)是指树上的最长简单路。
直径的求法:两遍BFS (or DFS)
任选一点u为起点,对树进行BFS遍历,找出离u最远的点v
以v为起点,再进行BFS遍历,找出离v最远的点w。则v到w的路径长度即为树的直径
*简单证明
于是原问题可以在O(E)时间内求出
关键在于证明第一次遍历的正确性,也就是对于任意点u,距离它最远的点v一定是最长路的一端。
如果u在最长路上,那么v一定是最长路的一端。可以用反证法:假设v不是最长路的一端,则存在另一点v’使得(u→v’)是最长路的一部分,于是len(u→v’) > len(u→v)。但这与条件“v是距u最远的点”矛盾。
如果u不在最长路上,则u到其距最远点v的路与最长路一定有一交点c,且(c→v)与最长路的后半段重合(why?),即v一定是最长路的一端
//方法2,两次BFS,1110MS
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
#define MAXN 40001
struct ENode
{
int adv,dis;
};
vector<ENode> adjlist[MAXN];
int N,ans,dis[MAXN],queue[MAXN],front,rear;
bool visited[MAXN];
int bfs1(int u)
{
front=rear=-1;
queue[++rear]=u;
int i,v;
while(front<rear)
{
i=queue[++front];
visited[i]=true;
for(vector<ENode>::size_type j=0;j<adjlist[i].size();j++)
{
v=adjlist[i][j].adv;
if(!visited[v]) queue[++rear]=v;
}
}
return queue[rear];
}
void bfs2(int u)
{
front=rear=-1;
queue[++rear]=u;
int i,v;
while(front<rear)
{
i=queue[++front];
visited[i]=true;
for(vector<ENode>::size_type j=0;j<adjlist[i].size();j++)
{
v=adjlist[i][j].adv;
if(!visited[v])
{
queue[++rear]=v;
dis[v]=dis[i]+adjlist[i][j].dis;
if(dis[v]>ans) ans=dis[v];
}
}
}
}
int main()
{
int M,i,j,d;
ENode e;
char ch;
while(scanf("%d %d",&N,&M)!=EOF)
{
getchar();
while(M--)
{
scanf("%d %d %d %c",&i,&j,&d,&ch);
e.adv=j;
e.dis=d;
adjlist[i].push_back(e);
e.adv=i;
adjlist[j].push_back(e);
getchar();
}
memset(visited,false,sizeof(*visited)*(N+1));
int v=bfs1(1);
memset(visited,false,sizeof(*visited)*(N+1));
memset(dis,0,sizeof(dis));
ans=-1;
bfs2(v);
printf("%d\n",ans);
}
return 0;
}
浙公网安备 33010602011771号