1. 程式人生 > >[ACM]Magical Girl Haze

[ACM]Magical Girl Haze

ron string pre 決定 style 最短 gic 技術 ems

一、題面

技術分享圖片

樣例輸入:

1
5 6 1
1 2 2
1 3 4
2 4 3
3 4 1
3 5 6
4 5 2

樣例輸出:

3

來源:ACM-ICPC 2018 南京賽區網絡預賽

二、思路

關鍵詞:分層BFS

考試時覺得題幹意思很清晰——求可將k條邊賦值為0的最短路。起初幾個思路正確性均存疑,後來覺得應該要DP於是決定滯後了。。。

正解——分層BFS,個人認為思路與DP有些許相像,同時記錄節點及當前已賦值為0的邊數,則在跑最短路時(這裏用的SPFA),可選擇是否將該條邊賦值為0,當且僅當已選邊<k。

三、代碼

 1 #include <cstdio>
 2 #include <cstring> 
 3
4 #define MAXN 100005 5 #define MAXM 200005 6 #define MAXK 15 7 #define INF 0x3f3f3f3f 8 9 int T, n, m, k, u, v, w, o, h[MAXN], d[MAXN][MAXK], vis[MAXN][MAXK]; 10 11 struct node { 12 int n, k; 13 } q[MAXN]; 14 15 struct edge { 16 int v, next, w; 17 } e[MAXM]; 18 19 void add(int u, int v, int
w) { 20 o++, e[o] = (edge) {v, h[u], w}, h[u] = o; 21 } 22 23 int spfa() { 24 int head = 1, tail = 2; 25 memset(d, INF, sizeof(d)), memset(vis, 0, sizeof(vis)); 26 q[head] = (node) {1, 0}, d[1][0] = 0, vis[1][0] = 1; 27 while (head != tail) { 28 node o = q[head]; 29 vis[o.n][o.k] = 0
; 30 for (int x = h[o.n]; x; x = e[x].next) { 31 int v = e[x].v; 32 if (d[v][o.k] > d[o.n][o.k] + e[x].w) { 33 d[v][o.k] = d[o.n][o.k] + e[x].w; 34 if (!vis[v][o.k]) vis[v][o.k] = 1, q[tail++] = (node) {v, o.k}; 35 } 36 if (o.k < k) { 37 if (d[v][o.k + 1] > d[o.n][o.k]) { 38 d[v][o.k + 1] = d[o.n][o.k]; 39 if (!vis[v][o.k + 1]) vis[v][o.k + 1] = 1, q[tail++] = (node) {v, o.k + 1}; 40 } 41 } 42 } 43 head++; 44 } 45 return d[n][k]; 46 } 47 48 int main() { 49 scanf("%d", &T); 50 for (int i = 1; i <= T; i++) { 51 o = 0, memset(h, 0, sizeof(h)); 52 scanf("%d %d %d", &n, &m, &k); 53 for (int j = 1; j <= m; j++) scanf("%d %d %d", &u, &v, &w), add(u, v, w); 54 printf("%d\n", spfa()); 55 } 56 return 0; 57 }

多個子問題著重考慮各種初始化!

[ACM]Magical Girl Haze