【SPFA】【最短路/次短路】GF打Dota
GF打Dota
題目大意:
求一個點到另一個點的最短路或次短路
原題:
題目描述
眾所周知,GF同學喜歡打dota,而且打得非常好。今天GF和Spartan同學進行了一場大戰。現在GF拿到一張地圖,地圖上一共有n個地點,GF的英雄處于1號點,Spartan的基地位于n號點,GF要盡快地選擇較短的路線讓他的英雄去虐掉Spartan的基地。但是Spartan早就料到了這一點,他有可能會開掛(BS~)使用一種特別的魔法,一旦GF所走的路線的總長度等于最短路的總長度時,GF的英雄就要和這種魔法糾纏不休。這時GF就不得不選擇非最短的路線。現在請你替GF進行規劃。
對于描述的解釋與提醒:
1.無向路徑,花費時間當然為非負值。
2.對于本題中非最短路線的定義:不管采取任何迂回、改道方式,只要GF所走的路線總長度不等于1到n最短路的總長度時,就算做一條非最短的路線。
3.保證1~n有路可走。
輸入
第一行為n,m(表示一共有m條路徑)
接下來m行,每行3個整數a,b,c,表示編號為a,b的點之間連著一條花費時間為c的無向路徑。
接下來一行有一個整數p,p=0表示Spartan沒有開掛使用這種魔法,p=1則表示使用了。
輸出
所花費的最短時間t,數據保證一定可以到達n。
輸入樣例
樣例輸入1:
5 5 1 2 1 1 3 2 3 5 2 2 4 3 4 5 1 0樣例輸入2:
5 5 1 2 1 1 3 2 3 5 2 2 4 3 4 5 1 1輸出樣例
樣例輸出1:
4
樣例輸出2:
5
說明
對于50%的數據,1<=n,m<=5000
對于70%的數據,1<=n<=10000, 1<=m<=50000,p=0,
對于100%的數據,1<=n<=10000, 1<=m<=50000,p=1
無向圖,花費時間c>=0
解題思路:
正著跑一遍SPFA,是第一個點到每一個點的最短路(a),倒著跑一遍SPFA,是每個點到n的最短路(b),如果是最短路就直接輸出,如果是次短路,就枚舉每一條邊,將其中一個點的a和另一個點的b再加上這條邊的長度,求出這條路線的長度,在這些中找出次短路即可
代碼:
#include<cstdio> #include<cstring> #include<iostream> #include<queue> using namespace std; int n,m,x,y,c,w,pp,now,ans,sum,aa[50005],bb[50005],cc[50005],b[10005],b1[10005],p[10005],head[10005]; struct rec {int to,next,l; }a[100005]; int main() {scanf("%d %d",&n,&m);for (int i=1;i<=m;++i){scanf("%d %d %d",&x,&y,&c);aa[i]=x;//記錄線bb[i]=y;cc[i]=c;a[++w].to=y;//鄰接表a[w].l=c;a[w].next=head[x];head[x]=w;a[++w].to=x;//雙向a[w].l=c;a[w].next=head[y];head[y]=w;}scanf("%d",&pp);memset(b,127/3,sizeof(b));memset(b1,127/3,sizeof(b1));queue<int>d;d.push(1);b[1]=0;p[1]=1;while(!d.empty())//正著{now=d.front();d.pop();for (int i=head[now];i;i=a[i].next)if (b[now]+a[i].l<b[a[i].to]){b[a[i].to]=b[now]+a[i].l;if (!p[a[i].to]){p[a[i].to]=1;d.push(a[i].to);}}p[now]=0;}if (!pp){printf("%d",b[n]);return 0;}sum=b[n];d.push(n);b1[n]=0;p[n]=1;while(!d.empty())//倒著{now=d.front();d.pop();for (int i=head[now];i;i=a[i].next)if (b1[now]+a[i].l<b1[a[i].to]){b1[a[i].to]=b1[now]+a[i].l;if (!p[a[i].to]){p[a[i].to]=1;d.push(a[i].to);}}p[now]=0;}ans=2147483647;for (int i=1;i<=m;++i){if (b[aa[i]]+b1[bb[i]]+cc[i]>sum)//連接線ans=min(ans,b[aa[i]]+b1[bb[i]]+cc[i]);if (b[bb[i]]+b1[aa[i]]+cc[i]>sum)//反過來ans=min(ans,b[bb[i]]+b1[aa[i]]+cc[i]);}printf("%d",ans); }總結
以上是生活随笔為你收集整理的【SPFA】【最短路/次短路】GF打Dota的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 老用户眼中的苹果2021款iMac,优点
- 下一篇: 【DFS】排排坐