很久以前,T王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。
为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。
J是T国重要大臣,他巡查于各大城市之间,体察民情。所以,从一个城市马不停蹄地到另一个城市成了J最常做的事情。他有一个钱袋,用于存放往来城市间的路费。
聪明的J发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第x千米到第x+1千米这一千米中(x是整数),他花费的路费是x+10这么多。也就是说走1千米花费11,走2千米要花费23。
J大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?
输入的第一行包含一个整数n,表示包括首都在内的T王国的城市数
城市从1开始依次编号,1号城市为首都。
接下来n-1行,描述T国的高速路(T国的高速路一定是n-1条)
每行三个整数Pi, Qi, Di,表示城市Pi和城市Qi之间有一条高速路,长度为Di千米。
输出一个整数,表示大臣J最多花费的路费是多少。
1 2 2
1 3 1
2 4 5
2 5 4
大臣J从城市4到城市5要花费135的路费。
根据性质来看,这是一棵树找最大权值路径问题,和求一棵树的直径是一样的。
一开始不知道一个理论走了很多弯路。
由于数据n有一个10000的我们不可能开一个10000*10000的数组,你可以用结构体来表示边之间的关系,我是用了两个map
map<int,vector<int>> t,第一个int表示节点编号,第二个vector用来盛放与这个节点又直接边相连的节点。
map<pair<int,int>,int> dist pair二元组用来盛放两节点编号,后面用来盛放两节点距离
例如输入 1 2 2,即1号城市与2号城市之间距离为2
那么应该这样存储这条信息。
t[1].push_back(2);
t[2].push_back(1);
dist[make_pair(1,2)]=2;
至于map,vector怎么用,可以百度一下
一开始不知道两遍DFS/BFS两遍就可以,把所有节点都遍历了一遍,结果都是75分
先贴75分代码:
1.DFS:
#include <iostream>
#include <map>
#include <vector>
#include <cstring>
using namespace std;
map<int,vector<int> > t;
map<pair<int,int>,int> dis;
int visited[10001];
int mdis=0;
void DFS(int i,int d)
{
if(!visited[i])
{
visited[i]=1;
if(d>mdis)
mdis=d;
for(int j=0;j<t[i].size();j++)
{
if(!visited[t[i][j]])//t[i][j]表示t[i]数组中第j个元素
{
pair<int,int> tmp(i,t[i][j]);
DFS(t[i][j],d+dis[tmp]);
}
}
}
}
int main()
{
int n,a,b,d,cost=0;
cin>>n;
for(int i=0;i<n-1;i++)
{
cin>>a>>b>>d;
t[a].push_back(b);
t[b].push_back(a);
dis[make_pair(a,b)]=d;
dis[make_pair(b,a)]=d;
}
for(int i=1;i<=n;i++)
{
memset(visited,0,sizeof(visited));
DFS(i,0);
}
for(int i=1;i<=mdis;i++)
cost+=(10+i);
cout<<cost<<endl;
return 0;
}
2.BFS
#include <iostream>
#include <map>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
map<int,vector<int> > t;
map<pair<int,int>,int> dist;
queue<int> q;
int visited[10001];
int dis[10001];
int mdis=0,n,pos;
int BFS(int x)
{
int tmp,Max=0;
q.push(x);
visited[x]=1;
while(!q.empty())
{
tmp=q.front();
for(int i=0;i<t[tmp].size();i++)
if(!visited[t[tmp][i]])
{
pair<int,int> dit(tmp,t[tmp][i]);
q.push(t[tmp][i]);
visited[t[tmp][i]]=1;
dis[t[tmp][i]]=dis[tmp]+dist[dit];//dis用来放x节点到t[tmp][i]节点距离
}
q.pop();
}
for(int i=1;i<=n;i++)//找出从x出发距离最大的路径
if(Max<dis[i])
{
Max=dis[i];
pos=i;
}
return Max;
}
int main()
{
int a,b,d,cost=0,tmp;
cin>>n;
for(int i=0;i<n-1;i++)
{
cin>>a>>b>>d;
t[a].push_back(b);
t[b].push_back(a);
dist[make_pair(a,b)]=d;
dist[make_pair(b,a)]=d;
}
for(int i=1;i<=n;i++)
{
memset(visited,0,sizeof(visited));
memset(dis,0,sizeof(dis));
tmp=BFS(i);
if(tmp>mdis)
mdis=tmp;
}
for(int i=1;i<=mdis;i++)
cost+=(10+i);
cout<<cost<<endl;
return 0;
}
其实我们想想,如果我们知道根节点是哪一个的话,是不是就简单了很多
就像求树的直径(树的直径:是树中所有最短路径长度中的最大值)那样,两遍BFS/DFS。
在树的直径中,我们先遍历一遍,随便找一个节点为根节点,找出最长路(长度为数的高度)的终点即叶节点,那么,这个叶节点一定是树的直径的一个端点。我们只需再以这个叶节点为根节点遍历一遍,再找到一个叶子节点,这两个叶子节点间的路径就是树的直径的路径。
同样的:
拿这个题来说:
第一遍遍历,随便找一个点i遍历一遍,找出一个距离i最远的点x,则x一定是最终我们要找的那条路径的一个端点
第二次只需要从x这个点遍历一遍找出距离x最远的点y,x->y的花费即为我们要求得结果
AC代码:
1.DFS
#include <iostream>
#include <map>
#include <vector>
#include <cstring>
using namespace std;
map<int,vector<int> > t;
map<pair<int,int>,int> dis;
int visited[10001];
int mdis=0,pos;
void DFS(int i,int d)
{
if(!visited[i])
{
visited[i]=1;
if(d>mdis)
{
pos=i;
mdis=d;
}
for(int j=0;j<t[i].size();j++)
if(!visited[t[i][j]])
{
pair<int,int> tmp(i,t[i][j]);
DFS(t[i][j],d+dis[tmp]);
}
}
}
int main()
{
int n,a,b,d,cost=0;
cin>>n;
for(int i=0;i<n-1;i++)
{
cin>>a>>b>>d;
t[a].push_back(b);
t[b].push_back(a);
dis[make_pair(a,b)]=d;
dis[make_pair(b,a)]=d;
}
memset(visited,0,sizeof(visited));//一定不要忘记两次置零
DFS(1,0);//找到一个端点
memset(visited,0,sizeof(visited));
DFS(pos,0);
for(int i=1;i<=mdis;i++)
cost+=(10+i);
cout<<cost<<endl;
return 0;
}
2.BFS:
#include <iostream>
#include <map>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
map<int,vector<int> > t;
map<pair<int,int>,int> dist;
queue<int> q;
int visited[10001];
int dis[10001];
int mdis=0,n,pos;
int BFS(int x)
{
int tmp,Max=0;
q.push(x);
visited[x]=1;
while(!q.empty())
{
tmp=q.front();
for(int i=0;i<t[tmp].size();i++)
if(!visited[t[tmp][i]])
{
pair<int,int> dit(tmp,t[tmp][i]);
q.push(t[tmp][i]);
visited[t[tmp][i]]=1;
dis[t[tmp][i]]=dis[tmp]+dist[dit];
}
q.pop();
}
if(Max<dis[i])
{
Max=dis[i];
pos=i;
}
return Max;
}
int main()
{
int a,b,d,cost=0,tmp;
cin>>n;
for(int i=0;i<n-1;i++)
{
cin>>a>>b>>d;
t[a].push_back(b);
t[b].push_back(a);
dist[make_pair(a,b)]=d;
dist[make_pair(b,a)]=d;
}
memset(visited,0,sizeof(visited));
memset(dis,0,sizeof(dis));
BFS(1);
memset(visited,0,sizeof(visited)); //一定不要忘记两遍置零
memset(dis,0,sizeof(dis));
mdis=BFS(pos);
for(int i=1;i<=mdis;i++)
cost+=(10+i);
cout<<cost<<endl;
return 0;
}