时间与空间之旅 解题报告
時(shí)間與空間之旅
Time Limit:1000MS? Memory Limit:65536K
Description
公元22XX年,宇宙里最普遍的交通工具是spaceship。Spaceship的出現(xiàn)使得星系之間的聯(lián)系變得更為緊密,所以spaceship船長(zhǎng)也成了最熱門的職業(yè)之一。當(dāng)然,要成為一名出色的船長(zhǎng),必須通過(guò)嚴(yán)格的考核,例如下面是最簡(jiǎn)單的問(wèn)題中的一個(gè):
用1~n的整數(shù)給n個(gè)星系標(biāo)號(hào),目前你在標(biāo)號(hào)為1的星系,你需要送快遞到標(biāo)號(hào)為n的星系,星系之間由于存在隕石帶,并不是都可以直連的。同時(shí),由于超時(shí)空隧道的存在,在某些星系間飛行會(huì)出現(xiàn)時(shí)間靜止甚至倒流,飛行時(shí)間為0或?yàn)樨?fù)數(shù)。另外,由星系i到星系j的時(shí)間和由星系j到星系i的時(shí)間不一定是相同的。
在寄出日期之前收到快遞被認(rèn)為是不允許的,所以每部spaceship上都有一個(gè)速度調(diào)節(jié)裝置,可以調(diào)節(jié)飛行的時(shí)間。簡(jiǎn)單來(lái)說(shuō)其功能就是讓所有兩個(gè)星系間的飛行時(shí)間(如果可以直達(dá)的話)都增加或減少相同的整數(shù)值,你的任務(wù)就是調(diào)整速度調(diào)節(jié)器,找出一條用最短的時(shí)間完成任務(wù)的路徑,并且保證這個(gè)最短時(shí)間的值大于或等于0。
Input
輸入文件tstrip.in 包含多組數(shù)據(jù),第一個(gè)數(shù)為T,表示數(shù)據(jù)的數(shù)量。
對(duì)于每一組數(shù)據(jù),輸入第一行為兩個(gè)正整數(shù)N(2≤N≤100),E(1≤E≤N*(N-1)/2),為星系的個(gè)數(shù)和星系間飛行的路線數(shù)。然后E行,每行三個(gè)整數(shù)i,j和t(1≤i,j≤N, i≠j, -100000≤t≤100000),表示由星系i到星系j飛行的時(shí)間為t。由i到j(luò)最多只會(huì)有一條飛行線路。
Output
輸出文件tstrip.out一共T行,每組數(shù)據(jù)輸出一行:
如果可以通過(guò)調(diào)節(jié)速度調(diào)節(jié)器完成任務(wù),則輸出一個(gè)非負(fù)整數(shù),表示由星系1到星系N的最短時(shí)間。
如果不能由星系1到達(dá)星系N,則輸出-1.
Sample Input
1 4 5 1 2 1 1 3 1 2 3 -3 3 1 1 3 4 1Sample Output
2Hint
輸入樣例如圖所示,其中結(jié)點(diǎn)標(biāo)號(hào)表示相應(yīng)星系,結(jié)點(diǎn)間數(shù)字表示所需時(shí)間。
如果設(shè)置速度控制器的值為0,則有如下路徑:1->2->3->1->2->……->3->4,使得投遞的時(shí)間為負(fù)無(wú)窮大,顯然是不符合要求的,所以應(yīng)該把速度控制器的值設(shè)為1,相當(dāng)于每個(gè)時(shí)間值加1,得到的最短路徑為1->2->3->4,所需時(shí)間為2+(-2)+2=2。
Source
GDOI2007
本題的解法是二分+spfa。
二分需要調(diào)整的飛行時(shí)間,spfa處理時(shí)把每條邊都減去該飛行時(shí)間,當(dāng)1到n的最短時(shí)間大于等于0時(shí),符合條件,縮小二分右邊界。
對(duì)于不符合條件的情況:
1、1不能到達(dá)n,這需要在二分前用floyed傳遞閉包(判斷連通性)預(yù)處理判斷;若出現(xiàn)此種情況,直接輸出-1毋需二分;
2、1可以到達(dá)n,但最短路上存在負(fù)環(huán),這時(shí)縮小左邊界;
值得注意的是,有負(fù)環(huán)也并非一定不成立,只要負(fù)環(huán)不在最短路上(換句話說(shuō),即是負(fù)環(huán)上的點(diǎn)與n不連通),也是可能成立的;
3、1到n最短時(shí)間小于0.
細(xì)節(jié)處理比較多,比較容易錯(cuò)的就是負(fù)環(huán)的處理。
如何判斷負(fù)環(huán)是否在最短路上?只要當(dāng)前將拓展的點(diǎn)與n不連通,就不進(jìn)行拓展,當(dāng)然如果當(dāng)前點(diǎn)已經(jīng)為n,還是需要更新最短時(shí)間的。另外,與題目不符,數(shù)據(jù)中有自環(huán)。
(如果你死活過(guò)不了,請(qǐng)認(rèn)真對(duì)比下程序,很可能就是某個(gè)細(xì)節(jié)出了問(wèn)題)
代碼:
#include<cstdio> #include<cstring> using namespace std;int t,n,e,top;int a[101][101];int stack[101];int dist[101];int fre[101];bool f[101][101];bool visited[101]; bool check(int del) //檢查是否滿足條件 {top=1;stack[1]=1;memset(dist,0x7f7f,sizeof(dist));dist[1]=0;memset(visited,false,sizeof(visited));visited[1]=true;memset(fre,0,sizeof(fre));fre[1]=1;while (top>0){int now=stack[top];top--;visited[now]=false;for (int i=1;i<=n;i++)if (a[now][i]<=100000)if (dist[now]+a[now][i]-del<dist[i]&&f[i][n]){dist[i]=dist[now]+a[now][i]-del;if (!visited[i]&&fre[i]<=n) //判負(fù)環(huán),由于已經(jīng)保證當(dāng)前點(diǎn)與n連通,故只要為負(fù)環(huán)可直接返回false{visited[i]=true;stack[++top]=i;fre[i]++;if (fre[i]>n) return false;}}}if (dist[n]>=0) return true; else return false; } void floyd() //floyed傳遞閉包判斷連通性 {for (int k=1;k<=n;k++)for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)if (f[i][k]&&f[k][j])f[i][j]=true; } int main() {scanf("%d",&t);while (t!=0){t--;scanf("%d%d",&n,&e);int l=2147483647;int r=-2147483647;memset(a,0x7f7f,sizeof(a));memset(f,false,sizeof(f));for (int i=1;i<=n;i++) f[i][i]=true;for (int i=1;i<=e;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);if (a[u][v]>w) a[u][v]=w;f[u][v]=true;if (w>r) r=w;if (w<l) l=w;}floyd();if (!f[1][n]) //非連通直接輸出-1{printf("-1\n");continue;}int ans;while (l<=r){int mid=(l+r)/2;if (check(mid)) {l=mid+1; ans=dist[n];} else r=mid-1;}printf("%d\n",ans);}return 0; }總結(jié)
以上是生活随笔為你收集整理的时间与空间之旅 解题报告的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 目标检测 YOLOv5网络v6 0版本总
- 下一篇: 基于jsDelivr+GitHub的免费