本文主要是介绍蓝桥杯-专题-简单图论(大臣旅费网络寻路),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
很久没写题了,最近就刷刷蓝桥杯,本来图论写的少,就接触过初级的最短路,现在就是练练手
1.大臣旅费
题目
很久以前,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最多花费的路费是多少。
样例输入:
5
1 2 2
1 3 1
2 4 5
2 5 4
样例输出:
135
样例说明:
大臣J从城市4到城市5要花费135的路费。
资源约定:
峰值内存消耗 < 64M
CPU消耗 < 5000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
思路
我觉得的呀!好像挺容易想到找两个距离最长的点就行,就是这两个点叫“树的直径”。然后直径的简单求解就是:从任意一点出发,进行一遍搜索(BFS/DFS)找直径的一个端点;在从这个端点出发,再进行一遍搜索(DFS/BFS)找直径的另一个端点。直径求出来就行了。
数据结构,我就用的普通的邻接表和邻接矩阵。 链式前向星不太会呀。。。
代码
#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))//不能mem(double)
#define ll long long
const double eps=3e-8;
const int mod=10;
const int maxn=10005;//最好数量范围大一点;1e4+5 && long long
vector<int>ed[maxn];//存储每个点的邻接点
ll edge[maxn][maxn];//存储每个边值
ll dis[maxn];//存储bfs中从node点开始的路径长
ll sum=0;
int bfs(int node){mem(dis,-1);queue<int>que;que.push(node);int ans=node;dis[node]=0;while(!que.empty()){int now=que.front();que.pop();for(int i=0;i<ed[now].size();i++){int temp=ed[now][i];if(dis[temp]<0){dis[temp]=dis[now]+edge[now][temp];if(dis[temp]>sum){ans=temp;sum=dis[temp];}que.push(temp);}}}return ans;
}
int main(){freopen("in4.txt","r",stdin);int n,a,b;ll c;scanf("%d",&n);for(int i=1;i<n;i++){scanf("%d%d%lld",&a,&b,&c);ed[a].push_back(b);ed[b].push_back(a);edge[a][b]=c;edge[b][a]=c;}int starta=1;int endnode,startnode;sum=0;endnode=bfs(starta);sum=0;startnode=bfs(endnode);///cout<<endnode<<" "<<startnode<<" "<<sum<<endl;double ans=sum*(sum+1.0)/2+10.0*sum;printf("%.0f\n",ans);
}
2.网络寻路
题目
图一
X 国的一个网络使用若干条线路连接若干个节点。节点间的通信是双向的。某重要数据包,为了安全起见,必须恰好被转发两次到达目的地。该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种不同的转发路径。
源地址和目标地址可以相同,但中间节点必须不同。
如图1所示的网络。
1 -> 2 -> 3 -> 1 是允许的
1 -> 2 -> 1-> 2 或者 1->2->3->2 都是非法的。
输入数据的第一行为两个整数N M,分别表示节点个数和连接线路的条数(1<=N<=10000; 0<=M<=100000)。
接下去有M行,每行为两个整数 u 和 v,表示节点u 和 v 联通(1<=u,v<=N , u!=v)。
输入数据保证任意两点最多只有一条边连接,并且没有自己连自己的边,即不存在重边和自环。
输出一个整数,表示满足要求的路径条数。
例如:
用户输入:
3 3
1 2
2 3
1 3
则程序应该输出:
6
再例如:
用户输入:
4 4
1 2
2 3
3 1
1 4
则程序应该输出:
10
资源约定:
峰值内存消耗 < 64M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型(千万不要混淆c和cpp)。
思路
这里是引用答案。
[题意]
给你一个图,N个节点,M条无向边.
问你从任意节点走3步后,到达另外一个节点的走法数有多少种(开始位置和结束位置可能相同,也就是走三元环)
[解析]
走3步,也就是走了三条边.
那么我们可以枚举三条边的中间那条边为edge(u,v).
那么: (节点u连出去的边数-1)(节点v连出去的边数-1); 就是第二步走中转边edge(u,v)的方法数.
所以只要枚举每条边作为中转边的方法数之和为ans即可.
因为边是双向的,所以最后答案ans2即为最终结果.
只要想到通过中转边来统计,此题就是不难了.
这大概就是枚举的奥妙!~ 我本来从两头找中间,但是好像时间复杂度不太像,于是后来改成从中间找两头了。
代码
#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))//不能mem(double)
#define ll long long
const double eps=3e-8;
const int mod=10;
const int maxn=10005;//最好数量范围大一点;1e4+5 && long long
vector<int>ed[maxn];//存储每个点的邻接点
ll sum=0;
struct node{ll from,to;node(int x,int y):from(x),to(y){}node(){}
};
vector<node>edges;
int main(){freopen("in5.txt","r",stdin);ll n,m,a,b;scanf("%lld%lld",&n,&m);for(int i=0;i<m;i++){scanf("%lld%lld",&a,&b);ed[a].push_back(b);ed[b].push_back(a);edges.push_back(node(a,b));}ll ans=0;for(int i=0;i<edges.size();i++){int from=edges[i].from;int to=edges[i].to;ans+=(ed[from].size()-1)*(ed[to].size()-1);}cout<<ans*2LL<<endl;return 0;
}
这篇关于蓝桥杯-专题-简单图论(大臣旅费网络寻路)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!