T1:树的直径
【题目描述】
⼀一棵树的直径指的是树中距离最远的两点间的距离。给出一颗无根树,请你求出它的直径。
【输入】
输入的第1包含1个整数n,表示树中节点个数。
接下来的n-1,每行有3个整数u,v,w。表示存在一条从u到v,长度为w的边。
【输出】
输出一行,包含1个整数,即树的直径。
【输入输出样例】
INPUT: OUTPUT
6 13
1 2 3
1 3 4
2 4 2
4 6 3
2 5 6
【输入输出样例解释】
直径为 3->1->2->5 ,总长度为13。
对于30%的数据,有2≤N≤100。
对于50%的数据,有2≤N≤3000。
对于70%的数据,有2≤N≤100,000。
对于100%的数据,有2≤N≤500,000,1≤u,v≤N,1≤w≤10000。
T2:羊驼村庄
【问题描述】
在宽广的马勒戈壁上有n个村庄和n - 1条无向道路,村庄之间两两可达,道路有长度。给你马勒戈壁的地图,统计这样一个信息:对于每个村庄,离它最远的那个村庄有多远?
【输入格式】
第一行包含一个正整数n,表示村庄数。
以下n – 1行每行包含x, y, z三个整数表示村庄x至村庄y存在一条长度为z的道路。
【输出格式】
输出包含n行,第i行输出离村庄i最远村庄的距离。
【样例输入1】
3
1 2 1
1 3 2
【样例输出1】
2
3
3
【样例输入2】
7
1 2 1
2 3 1
3 4 1
4 5 1
5 6 1
6 7 1
【样例输出2】
6
5
4
3
4
5
6
【数据规模和约定】
对于30%的数据,n <= 2000;
对于60%的数据,n <= 20000;
对于100%的数据,1 <= n <= 200000,道路长度非负,且所有道路的长度之和不大于109。
---------------------------------------------------------------------------------------------
----------------我是分割线-----------初次看题的可以先考虑一下-------------------------------------------------------------------------------------------------------------------------------
TI题解:
算法一:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;
int n,now(0),ans(0),bj(0);
queue<int>Q;
struct edge
{
int u,v,z;
edge *next;
}e[500005*2],*p=e,*point[500005*2];
void addedge(int x,int y,int z)
{
p++;p->u=y;p->v=z;p->next=point[x];
point[x]=p;
}
int dis[500005],used[500005];
inline void spfa(int x)//这里没用bfs/dfs,而是用了SPFA,虽然慢,但题解的dfs也超了两个点。。。
{
memset(dis,0x7f,sizeof(dis));
memset(used,0,sizeof(used));
Q.push(x);
used[x]=1;
dis[x]=0;
while(!Q.empty())
{
x=Q.front();Q.pop();used[x]=0;
for(p=point[x];p;p=p->next)
{
if(dis[p->u]>dis[x]+p->v)
{
dis[p->u]=dis[x]+p->v;
if(!used[p->u])used[p->u]=1,Q.push(p->u);
}
}
}
}
int main()
{
freopen("diameter.in","r",stdin);
freopen("diameter.ans","w",stdout);
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
addedge(x,y,z);
addedge(y,x,z);
}
spfa(1);//随便找一个点A
for(int i=1;i<=n;i++)
{
if(dis[i]>now&&dis[i]!=dis[0])
{
now=dis[i];
bj=i;//找出与A距离最大的点
}
}
spfa(bj);
for(int i=1;i<=n;i++)
{
if(dis[i]>ans&&dis[i]!=dis[0])
{
ans=dis[i];
}
}
printf("%d\n",ans);
return 0;
}
这道题主要是考思维。算法谁都会,就看思路对不对。这道题让我在小伙伴面前ZB,爽!
Fu[i] = max(fu[t], fd[t][0]) + w[i][t]
fd[i][1] = fd[i][0];
g[i][1] = g[i][0];
fd[i][0] = fd[j][0] + w[i][j];
g[i][0] = j;
} else if (fd[j][0] + w[i][j] > fd[i][1]) {
fd[i][1] = fd[j][0] + w[i][j];
g[i][1] = j;
}
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;
int n,now(0),bj(0),f[200005],maxx(0);
queue<int>Q;
struct edge
{
int u,v;
edge *next;
}e[200005*2],*p=e,*point[200005*2];
void addedge(int x,int y,int z)
{
p++;p->u=y;p->v=z;p->next=point[x];
point[x]=p;
}
int used[200005],dis[200005];
void SPFA(int x)
{
memset(used,0,sizeof(used));
memset(dis,0x7f,sizeof(dis));
Q.push(x);
used[x]=1;
dis[x]=0;
while(!Q.empty())
{
x=Q.front();Q.pop();used[x]=0;
for(edge *j=point[x];j;j=j->next)
{
if(dis[j->u]>dis[x]+j->v)
{
dis[j->u]=dis[x]+j->v;
if(!used[j->u])used[j->u]=1,Q.push(j->u);
}
}
}
}
int main()
{
freopen("village.in","r",stdin);
freopen("village.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
addedge(x,y,z);
addedge(y,x,z);
}
SPFA(1);
for(int i=1;i<=n;i++)
{
if(dis[i]>now)
{
now=dis[i];
bj=i;
}
}
SPFA(bj);
for(int i=1;i<=n;i++)
{
f[i]=dis[i];//找个数组先记下来SPFA(B)
}
for(int i=1;i<=n;i++)
{
if(dis[i]>maxx)
{
maxx=dis[i];
bj=i;
}
}
SPFA(bj);
for(int i=1;i<=n;i++)
{
f[i]=max(f[i],dis[i]);
}
for(int i=1;i<=n;i++)
printf("%d\n",f[i]);
return 0;
}
这个题让我又装了一次!嘿嘿嘿。。。