生活随笔
收集整理的這篇文章主要介紹了
迷阵突围
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
蒜頭君陷入了坐標系上的一個迷陣,迷陣上有 n 個點,編號從 1 到 n。蒜頭君在編號為 1 的位置,他想到編號為 n 的位置上。蒜頭君當然想盡快到達目的地,但是他覺得最短的路徑可能有風險,所以他會選擇第二短的路徑。現在蒜頭君知道了 n 個點的坐標,以及哪些點之間是相連的,他想知道第二短的路徑長度是多少。 注意,每條路徑上不能重復經過同一個點。
輸入格式 第一行輸入兩個整數 n (1≤n≤200) 和 m,表示一共有 n 個點和 m 條邊。 接下來輸入 n 行,每行輸入兩個整數 xi,yi (?500≤xi,yi≤500),代表第 i 個點的坐標。 接下來輸入 m 行,每行輸入兩個整數pj,qj(1≤pj,qj≤n),表示點 pj和點 qj之間相連。
輸出格式 輸出一行,輸出包含一個數,表示第二短的路徑長度(小數點后面保留兩位),如果第一短路徑有多條,則答案就是第一最短路徑的長度;如果第二最短路徑不存在,則輸出 ?1。
樣例輸入
3 3
1 1
2 2
3 2
1 2
2 3
1 3
樣例輸出
2.41
這道題可“第K短路”那道題是不同的,這道題要求每條路徑上不能重復經過同一個點,但是“第K短路”那道題沒有這個限制。 這道題的正確做法是在點1到點n的路徑上逐個將邊斷開,求最短路。
#include <bits/stdc++.h> #define pii pair<int,int>
#define dii pair<double,int>
using namespace std
;
const int N
= 205 , M
= 1e5 + 10 ;
int head
[ N
] , ver
[ M
] , Next
[ M
] , tot
= 1 ;
double edge
[ M
] , d
[ N
] ;
int pre
[ N
] ;
int v
[ N
] ;
vector
< pii
> p
;
int n
, m
; inline void add ( int x
, int y
, double z
) { ver
[ ++ tot
] = y
; edge
[ tot
] = z
; Next
[ tot
] = head
[ x
] ; head
[ x
] = tot
;
} inline void read ( ) { cin
>> n
>> m
; for ( int i
= 1 ; i
<= n
; i
++ ) { int x
, y
; scanf ( "%d%d" , & x
, & y
) ; p
. emplace_back ( x
, y
) ; } for ( int i
= 1 ; i
<= m
; i
++ ) { int x
, y
; double z
; scanf ( "%d%d" , & x
, & y
) ; z
= sqrt ( ( p
[ x
- 1 ] . first
- p
[ y
- 1 ] . first
) * ( p
[ x
- 1 ] . first
- p
[ y
- 1 ] . first
) + ( p
[ x
- 1 ] . second
- p
[ y
- 1 ] . second
) * ( p
[ x
- 1 ] . second
- p
[ y
- 1 ] . second
) ) ; add ( x
, y
, z
) ; add ( y
, x
, z
) ; }
} void spfa ( ) { for ( int i
= 2 ; i
<= n
; i
++ ) d
[ i
] = 1e9 , v
[ i
] = 0 ; d
[ 1 ] = 0 ; v
[ 1 ] = 1 ; queue
< int > q
; q
. push ( 1 ) ; while ( ! q
. empty ( ) ) { int x
= q
. front ( ) ; q
. pop ( ) ; v
[ x
] = 0 ; for ( int i
= head
[ x
] ; i
; i
= Next
[ i
] ) { int y
= ver
[ i
] ; double z
= edge
[ i
] ; if ( d
[ y
] > d
[ x
] + z
) { d
[ y
] = d
[ x
] + z
; pre
[ y
] = i
; if ( ! v
[ y
] ) { v
[ y
] = true ; q
. push ( y
) ; } } } }
} double dijkstra ( ) { for ( int i
= 1 ; i
<= n
; i
++ ) d
[ i
] = 1e9 , v
[ i
] = 0 ; priority_queue
< dii
> q
; d
[ 1 ] = 0 ; q
. push ( { 0 , 1 } ) ; while ( ! q
. empty ( ) ) { int x
= q
. top ( ) . second
; q
. pop ( ) ; if ( v
[ x
] ) continue ; v
[ x
] = 1 ; for ( int i
= head
[ x
] ; i
; i
= Next
[ i
] ) { int y
= ver
[ i
] ; double z
= edge
[ i
] ; if ( d
[ y
] > d
[ x
] + z
) { d
[ y
] = d
[ x
] + z
; q
. push ( { - d
[ y
] , y
} ) ; } } } return d
[ n
] ;
} inline void solve ( ) { if ( d
[ n
] == 1e9 ) { printf ( "-1" ) ; return ; } int tc
= n
; double mn
= 1e9 ; while ( pre
[ tc
] ) { double ke
= edge
[ pre
[ tc
] ] ; edge
[ pre
[ tc
] ] = edge
[ pre
[ tc
] ^ 1 ] = 1e9 ; mn
= min ( mn
, dijkstra ( ) ) ; edge
[ pre
[ tc
] ] = edge
[ pre
[ tc
] ^ 1 ] = ke
; tc
= ver
[ pre
[ tc
] ^ 1 ] ; } if ( mn
>= 1e9 ) printf ( "-1" ) ; else printf ( "%.2lf" , mn
) ;
} int main ( ) { read ( ) ; spfa ( ) ; solve ( ) ; return 0 ;
}
總結
以上是生活随笔 為你收集整理的迷阵突围 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。