日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

时间与空间之旅 解题报告

發布時間:2023/12/31 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 时间与空间之旅 解题报告 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

時間與空間之旅

Time Limit:1000MS? Memory Limit:65536K

Description

  公元22XX年,宇宙里最普遍的交通工具是spaceship。Spaceship的出現使得星系之間的聯系變得更為緊密,所以spaceship船長也成了最熱門的職業之一。當然,要成為一名出色的船長,必須通過嚴格的考核,例如下面是最簡單的問題中的一個:
  用1~n的整數給n個星系標號,目前你在標號為1的星系,你需要送快遞到標號為n的星系,星系之間由于存在隕石帶,并不是都可以直連的。同時,由于超時空隧道的存在,在某些星系間飛行會出現時間靜止甚至倒流,飛行時間為0或為負數。另外,由星系i到星系j的時間和由星系j到星系i的時間不一定是相同的。
  在寄出日期之前收到快遞被認為是不允許的,所以每部spaceship上都有一個速度調節裝置,可以調節飛行的時間。簡單來說其功能就是讓所有兩個星系間的飛行時間(如果可以直達的話)都增加或減少相同的整數值,你的任務就是調整速度調節器,找出一條用最短的時間完成任務的路徑,并且保證這個最短時間的值大于或等于0。

Input

輸入文件tstrip.in 包含多組數據,第一個數為T,表示數據的數量。
對于每一組數據,輸入第一行為兩個正整數N(2≤N≤100),E(1≤E≤N*(N-1)/2),為星系的個數和星系間飛行的路線數。然后E行,每行三個整數i,j和t(1≤i,j≤N, i≠j, -100000≤t≤100000),表示由星系i到星系j飛行的時間為t。由i到j最多只會有一條飛行線路。

Output

  輸出文件tstrip.out一共T行,每組數據輸出一行:
  如果可以通過調節速度調節器完成任務,則輸出一個非負整數,表示由星系1到星系N的最短時間。
  如果不能由星系1到達星系N,則輸出-1.

Sample Input

1 4 5 1 2 1 1 3 1 2 3 -3 3 1 1 3 4 1

Sample Output

2

Hint



  輸入樣例如圖所示,其中結點標號表示相應星系,結點間數字表示所需時間。
  如果設置速度控制器的值為0,則有如下路徑:1->2->3->1->2->……->3->4,使得投遞的時間為負無窮大,顯然是不符合要求的,所以應該把速度控制器的值設為1,相當于每個時間值加1,得到的最短路徑為1->2->3->4,所需時間為2+(-2)+2=2。



Source

GDOI2007


本題的解法是二分+spfa。

二分需要調整的飛行時間,spfa處理時把每條邊都減去該飛行時間,當1到n的最短時間大于等于0時,符合條件,縮小二分右邊界。

對于不符合條件的情況:

1、1不能到達n,這需要在二分前用floyed傳遞閉包(判斷連通性)預處理判斷;若出現此種情況,直接輸出-1毋需二分;

2、1可以到達n,但最短路上存在負環,這時縮小左邊界;

值得注意的是,有負環也并非一定不成立,只要負環不在最短路上(換句話說,即是負環上的點與n不連通),也是可能成立的;

3、1到n最短時間小于0.

細節處理比較多,比較容易錯的就是負環的處理。

如何判斷負環是否在最短路上?只要當前將拓展的點與n不連通,就不進行拓展,當然如果當前點已經為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) //判負環,由于已經保證當前點與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; }

總結

以上是生活随笔為你收集整理的时间与空间之旅 解题报告的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。