問題を解決するには - ゾンビ島を逃げた(BFS + +最短仮想ノード)
非常に巧妙な最短経路問題でなく、細部に注意を払います
フェイス質問
説明
小さな国侵略ライブゾンビ!国を脱出するために、国の唯一の国際空港に脱出する小計画。
国N都市は、接続されている都市間の道路があります。M双方向の道路があります。そして、重量はなし自己ループの端ことを確認します。
あなたが入ることができないので、K市は、制御されたゾンビは、... TATに突入場合に感染されますされています。そのうちのどれが他の都市に到達するために、市内の道路を通じてSを超えない、街は危険です。一つは距離sを超えない街に占有街に計上されていない限り、言い換えれば、それは危険です。
N個の都市で第1回国際空港で生活する小都市、二つの都市が侵略されていません。小さな散歩道路のすべてのストレッチ(市から直接別の都市に達する)全体の一日を過ごすために持っているので、夜はホテルに住んでいます。Pの元に安く安全な都市のホテルは、危険な都市、ホテルのセキュリティ対策が実施されるように、それはQの元のためのより高価になりますです。すべての危険な都市の宿泊代金と同様に、安全な都市あまりにも。都市とN、ノー滞在中に第1の都市。
けち比較的小さいが、ので、彼は必要な都市のNの数に1番街から最小コストを知りたいです。
パスがあることを確実にするために入力されたデータは、あなたが正常に脱出することができます。入力されたデータは、彼が正常に逃げることができることを確認します。
入力
4つの整数(N、M、K、S最初のライン )、
2行目の2の整数(P、Q)
次の行K、CIは、都市侵入ゾンビ表す
次にM行を、AI、BI、aは無向辺
出力
最小のコストを表す整数
in.1
13 21 1 1
1000年6000
7
1 2
3 7
2 4
5 8
8 9
2 5
3 4
4 7
9 10
10 11
5 10
7 12
3 6
4
1 3
11 12
6 7
8 11
6 13
7 8
12 13
out.1
11000
データ範囲と規則
データの20%を、N <= 50
データの100%、2≦N≦100000 ,. 1≦M≦200000、0≦K≦N - 2、0≦S≦100000
1≦P <Q≦100000
考え
これは、2つの部分に分け:
1.どのようなポイントの安全なノードの時点で危険なプロセスノード、です。
2.地方分権のために右側をタップします
治療:
1.は明らかに、すべてのBFSをデッドライジングにポイントを行うことはできませんが、明らかな理由は、重複したポイントは、複数のパスが、我々はちょうどVIS重い刑、アレイ間の深い関係の深さをカットオフするかどうかのポイントがありますされ、タイムアウトしました(この点を更新するために、より浅い点があってもよいです)。
そこで、我々はデッドライジングポイントの端にすべての方法であっても、仮想ソース・ポイントを設定します。(図のみビルドので、一方向側をssw02ので、それが返されてはならない)、より良好な深い点の深さとの関係を維持することができます。
2.この質問はすることができ、右側のうちのそれぞれの側に追加し、限り、我々は問題を扱うように、非常に特別な、一方向の側縁と先については、この辺の権利です。
詳細:
でも仮想ソース・ポイントの初期エッジに1つだけの方法。
図2は、唯一の場合は、右側には、最初のノート0、増加の後ろの右側です。
3.優先順位の注目の権利を縁取り!!
4.側権利を追加デッドライジングの点を打つ、両面がINF(厳密下の片側ラインにもプラスポイント)割り当てられている
ため、仮想エッジの数5のエッジを一方向100 000を増加させます側(2取るなくてもよいです)
ACコード:私は非常に簡単書きます
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int MAXN = 100005 , MAXM = 200005 + 100000 ;//多加的边数
inline int read(){
int s=0 ; char g=getchar() ;while(g>'9'||g<'0')g=getchar() ;
while(g>='0'&&g<='9')s=s*10+g-'0',g=getchar();return s ;
}
int N , M , K , S , Q1 , Q2 , head[ MAXN ] , danger[ MAXN ] , to[ MAXM*2 ] , nex[ MAXM*2 ] , tot = 1 ;
ll dis[ MAXN ] , w[ MAXM*2 ] ;
bool vis[ MAXN ] ;
priority_queue< pair<ll,int> >q ;
queue< pair<int,int> >ql ;
void add( int x , int y , int z ){
to[ ++tot ] = y , nex[ tot ] = head[ x ] ,w[ tot ] = z , head[ x ] = tot ;
}
void bfs(){
ql.push( make_pair(0,0) ) ;
vis[ 0 ] = true ;
while( !ql.empty() ){
int u = ql.front().first , dep = ql.front().second ; ql.pop() ;
for( int i = head[ u ] ; i ; i = nex[ i ] ){
if( vis[ to[ i ] ] || dep > S )continue ;
ql.push( make_pair( to[ i ] , dep+1 ) ) ;
vis[ to[i] ] = true , danger[ to[ i ] ] = max( danger[ to[i] ] , 1 ) ;
}
}
}
void dijkstra(){
for( int i = 1 ; i <= N ; ++i )dis[ i ] = 20000000005 ;//题意所得最大 20000000000
dis[ 1 ] = 0 ;
q.push( make_pair( 0LL,1 ) ) ;
while( !q.empty() ){
int u = q.top().second ; q.pop() ;
if( vis[ u ] )continue ;
vis[ u ] = true ;
for( register int i = head[ u ] ; i ; i = nex[ i ] ){
if( dis[ to[ i ] ] > dis[ u ] + w[ i ] ){
dis[ to[ i ] ] = dis[ u ] + w[ i ] ;
q.push( make_pair( -dis[ to[ i ] ] , to[ i ] ) ) ;
}
}
}
}
int main(){
N = read() , M = read() , K = read() , S = read() , Q1 = read() , Q2 = read() ;
int m1 , m2 ;
for( int i = 1 ; i <= K ; ++i ){
m1 = read() , danger[ m1 ] = 2 , add( 0 , m1 , 0 ) ;//单向
}
if( K%2 )tot++ ; K = tot ;
for( int i = 1 ; i <= M ; ++i ){
m1 = read() , m2 = read() ;
add( m1 , m2 , 0 ) ; add( m2 , m1 , 0 ) ;
}
bfs() ;
memset( vis , false , sizeof(vis) ) ;
for( int i = K ; i <= tot ; ++i ){//点权下放,分配边权
if( w[ i ] )continue ;
if( danger[ to[i] ] == 2 ){w[ i ] = w[ i^1 ] = 20000000005 ;}
else if( danger[ to[i] ] == 1 )w[ i ] = Q2 ;
else w[ i ] = Q1 ;
w[ i ] = ( to[ i ] == 1 || to[ i ] == N )? 0 : w[ i ] ;
}
dijkstra() ;
cout<<dis[ N ] ;
return 0 ;
}
42スコアssw02 - > 28 - > 57 - > 100はssw02がヒットしたものは本当にあります