[USACO06NOV] 路障 Roadblocks(次短路)
来源:互联网 发布:终极算法 txt 编辑:程序博客网 时间:2024/06/06 02:38
[USACO06NOV]路障Roadblocks
(来自Luogu)
题目描述
贝茜把家搬到了一个小农场,但她常常回到FJ的农场去拜访她的朋友。贝茜很喜欢路边的风景,不想那么快地结束她的旅途,于是她每次回农场,都会选择第二短的路径,而不象我们所习惯的那样,选择最短路。 贝茜所在的乡村有R(1<=R<=100,000)条双向道路,每条路都联结了所有的N(1<=N<=5000)个农场中的某两个。贝茜居住在农场1,她的朋友们居住在农场N(即贝茜每次旅行的目的地)。 贝茜选择的第二短的路径中,可以包含任何一条在最短路中出现的道路,并且,一条路可以重复走多次。当然咯,第二短路的长度必须严格大于最短路(可能有多条)的长度,但它的长度必须不大于所有除最短路外的路径的长度。
数据规模
见题干
思路
这是一个次短路的题目,与一楼的那位同学的方法比较类似,都有用到最短路的思想,但是我操作更新短路的时候用的SPFA,而且原理似乎更简单易懂一些。下面讲讲本人的思路,开两个数组存最小值min1和(严格)次小值min2,这一点一定要注意,题干中说了,这里是严格的次小值!
首先是SPFA的老套路,初始化1节点的min1和min2为0,其它节点的min1和min2为MAXX。
然后就是比较特殊的更新操作:(假设从u到v权值为w)
第一种情况,if(min1[v]>min1[u]+w),当前最小值min1[v]赋值给次小值min2[v],更新min1[u]+w为最小值min1[v];队列中若无v元素,则把v放入队列。
第二种情况,if(min2[v]>min1[u]+w),更新min1[u]+w为次小值min2[v];队列中若无v元素,则把v放入队列。
第三种情况,if(min2[v]>min2[u]+w),更新min2[u]+w为 次小值min2[v];队列中若无v元素,则把v放入队列。
一定要按上述顺序进行判断哦。
还有最重要的一点,由于题干中说可以来回走,而初始化中我们把min1[1]=min2[1]=0了,所以在1节点第一次被弹出队列之后一定要把它恢复成MAXX,否则第4个点会被卡掉。
最后更新完,队列空了之后,输出min2[n]即可。
我感觉我说的应该比较详细了,大概就是这样吧。
接下来上代码(C++):
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<queue>using namespace std;int i,j,m,n,s,temp;int y[200001],hd[5001],v[200001],nxt[200001];int min1[5001],min2[5001];int b[5001];queue<int>q;int r()//读入优化{ int aans=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { aans*=10; aans+=ch-'0'; ch=getchar(); } return aans*f;}void add(int xx,int yy,int zz)//建边{ y[++temp]=yy; v[temp]=zz; nxt[temp]=hd[xx]; hd[xx]=temp;}void spfa(){ int p,kk,kkk=0; while(!q.empty()) { if(b[1]==0&&!kkk)//1节点第一次弹出时,恢复1节点为MAXX min1[1]=0x7f7f7f,min2[1]=0x7f7f7f,kkk=1;//标记上,表示已经恢复过 int x=q.front(); p=hd[x]; q.pop(); b[x]=0; while(p) { if(min1[y[p]]>min1[x]+v[p])//上文所说的第一种情况 { kk=min1[y[p]];//赋值min2,更新min1 min1[y[p]]=min1[x]+v[p]; min2[y[p]]=kk; if(!b[y[p]])//对新节点进行判断,并放入队列 { q.push(y[p]); b[y[p]]=1; } } if(min2[y[p]]>min1[x]+v[p])//第二种情况 { if(min1[y[p]]!=min1[x]+v[p])//注意严格次短路 min2[y[p]]=min1[x]+v[p]; if(!b[y[p]])/对新节点进行判断,并放入队列 { q.push(y[p]); b[y[p]]=1; } } if(min2[y[p]]>min2[x]+v[p])//第三种情况 { if(min1[y[p]]!=min2[x]+v[p])//注意严格次短路 min2[y[p]]=min2[x]+v[p]; if(!b[y[p]])/对新节点进行判断,并放入队列 { q.push(y[p]); b[y[p]]=1; } } p=nxt[p]; }}}int main(){ memset(min1,0x7f7f7f,sizeof(min1));//初始化 memset(min2,0x7f7f7f,sizeof(min2)); n=r(),m=r(); int xx,yy,zz; for(i=1;i<=m;i++) { xx=r(),yy=r(),zz=r(); add(xx,yy,zz); add(yy,xx,zz); } q.push(1); b[1]=1; min1[1]=0,min2[1]=0; spfa(); cout<<min2[n];//输出}
- [USACO06NOV] 路障 Roadblocks(次短路)
- 【POJ3255】【洛谷2865】[Usaco2006 Nov]路障Roadblocks(次短路)
- Luogu 2865 [USACO06NOV]路障Roadblocks
- poj3255 Roadblocks (次短路)
- poj Roadblocks 次短路(数据较大)
- POJ 题目3255Roadblocks(次短路)
- POJ 3255 Roadblocks(次短路)
- POJ 3255 Roadblocks(次短路)
- Roadblocks(次短路-dijkstra算法)
- Roadblocks (次短路)(Dijkstra应用)
- poj 3255 Roadblocks(次短路)
- POJ 3255 Roadblocks (次短路问题)
- POJ 3255 Roadblocks(次短路)
- Roadblocks (SPFA次短路求法)
- POJ3255 Roadblocks , 次短路
- POJ3255 Roadblocks(次短路)
- POJ3255 Roadblocks 【次短路】
- POJ Roadblocks 次短路
- Python基础入门1--基础语法
- Android模拟器打不开或者模拟器找不到
- 3G 脚本
- 一个学渣的成长
- springMVC记录(一)
- [USACO06NOV] 路障 Roadblocks(次短路)
- hust 1010 最小循环节
- D-BUS基础编程
- clcaffe 出现warning: GStreamer: unable to query position of stream解决办法
- 第二章 2.3 快速排序
- poj3301 三分
- JointJS入门实例01-在JOINTJS元素中使用HTML
- c#循环中产生伪随机数_C#教程
- 推荐使用concurrent包中的Atomic类