P2939 [USACO09FEB]リメイクトレイルを刷新
タイトル説明
ファーマージョンは律儀に毎日牛にチェックします。彼はM(1 <= M <= 50,000)の一部が便利牧草N(テストデータに与えられたトレイルマップには常に可能である旅)に出牧場1からすべての方法を1..Mに番号が付けトレイル横断します。便利ファーマージョンの農場で1..Nに番号が付けN(1 <= N <= 10,000)の牧草地は、現在、双方向ダートトレイルで接続されています。各トレイルiは、牧草地P1_iとP2_i(1 <= P1_i <= N、1 <= P2_i <= N)を接続し、T_I横断する時間(1 <= T_I <= 1,000,000)単位を必要とします。
彼は彼の長い旅に時間を節約するために彼の農場でトレイルの一部を改造したいと考えています。具体的には、彼はK(1 <= K <= 20)を効果的に0ヘルプFJに歩道の横断時間を短縮するために牧場1から得ることの結果として時間を最小限にするために改造する証跡かを決めるであろう、高速道路に変身するために証跡を選択しますN.
TIMEのLIMIT:2秒
入力形式
1行目:スリースペースで区切られた整数:N、M、およびK
ライン2..M + 1:P1_i、P2_i、およびT_I:i線+ 1 iは3スペースで区切られた整数でトレイルを説明
出力フォーマット
- 行1:Kエッジ以下で改造しない後の最短経路の長さ
問題の意味の翻訳
ジョン、Nの合計)牧場。M証跡接続の塵でカバー。トレイルは、双方向のトラフィックをすることができます。毎朝ジョン牧場から牧場1のN牛身体検査へ。
それぞれを通るトレイルは、いくつかの時間を消費する必要があります。それは高速道路作り、道をアップグレードするジョン・K。高速道路上のトラフィックがほとんど瞬間なので、時間の経過は、高速道路がゼロです。
彼は毎日1号から第N牧場の牧草地への最短を過ごしたように、ジョンがアップグレードする証跡かを決定するのに役立ちます
サンプル入力と出力
入力#1
4 4 1
1 2 10
2 10 4
1 3 1
2 3 4 100
出力#1
1
説明/ヒント
Kは1です。改造道3->図4は、新たな最短パスが今1 1-> 3 - > 4、合計横断時間である代わりに100時間0を取ります。
[思考]
階層グラフ+のダイクストラ
階層図の裸のタイトル
あなたは、階層図を知りたい場合はこちらをご覧
階層グラフを理解します
[タイトル]効果
1からnまでのラン
kは道路に処理可能0となる
加工最低
[解析]タイトル
Kは、道路から削除することができ
、その質問のポスト電話線の内側を4回経験があるため、あなたが見たら
これだけこの質問ください
あなたは失望している可能性があり
そうであるように、ほとんどの電話回線を半分に使用されているが答え+ SPFA
3つの質問があることは、確かに、電話回線と知識です
が、この知識は半分ではなく、答え+ SPFAがグラフ階層
階層グラフは、特にこの問題のためであるが、k個の道路から削除することができます
が、それは必要大容量のメモリを開いて
、私は、階層図あれば知っているか、他の首長のブログを見るために、上記のリンクを見たいのですが
[コア]アイデア
被写体マップ生成所与のk番目
と二つの経路の間の接続は、図に0をマークされている
二つの図の間の通路が高速道路ということであるので
、私は私を番目の図の場合、高速道路の確立され
、その後、裸であります以下のように、実行中のダイクストラ
1-kのnは、高速道路オフ最後の比較は、出力端Sahuaに最も安価な内に到達します!!!
[完了コード】
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int Max = 4200005;
const int M = 420005;
struct point
{
int w;//路径的长度
int x;//点的标号
bool operator < (const point & xx)const
{
return xx.w < w;
}
};
struct node
{
int y,ne,z;
}a[Max];
int sum = 0,head[M];
void add(int x,int y,int z)
{
a[++ sum].y = y;
a[sum].ne = head[x];
a[sum].z = z;
head[x] = sum;
}
priority_queue<point>q;
int d[M];
bool use[M];
void dj()
{
memset(d,0x3f,sizeof(d));
d[1] = 0;
q.push((point){0,1});
while(!q.empty())
{
point qwq = q.top();
q.pop();
int x = qwq.x,w = qwq.w;
if(use[x] == true)
continue;
else
use[x] = true;
for(register int i = head[x];i != 0;i = a[i].ne)
{
int awa = a[i].y;
if(d[awa] > d[x] + a[i].z)
{
d[awa] = d[x] + a[i].z;
if(use[awa] == false)
q.push((point){d[awa],awa});
}
}
}
}
int main()
{
freopen("walk.in","r",stdin);
int n,m,k;
cin >> n >> m >> k;
for(register int i = 1;i <= m;++ i)
{
int x,y,z;
cin >> x >> y >> z;
add(x,y,z),add(y,x,z);
for(register int j = 1;j <= k;++ j)
{
add(j * n + x,j * n + y,z);
add(j * n + y,j * n + x,z);
add((j - 1) * n + x,j * n + y,0);
add((j - 1) * n + y,j * n + x,0);
}
}
dj();
int M = 0x7fffffff;
for(register int i = 0;i <= k;++ i)
M = min(M,d[i * n + n]);
cout << M << endl;
return 0;
}