上週考了道這個因爲段考到現在才改完這個 = =
這類問題嘛......算了我先放題目 就比如這個
很顯然問題都是最短路 然後中間可以跳邊走的那種
然後考場上我愣是想到了dp.....
好吧後來我也是在這個基礎上改的 不過這個就是叫分層圖最短路....
做法一:拆點 能免費幾條路就把一個點拆成多少個點 當然還要加1 (原始的) 連的話就是 x 和 y + n 連一個費用爲 0 的邊 x 和 y 連一個費用爲費用的邊 如果無向圖別忘了反過來
做法二:就像dp一樣 dis[p][k] 爲 到達 p 號點 使用 k 條免費路時最小的 dis 值 然後設 p 點到達 b 點 推導就是這樣個東西
這個應該分兩個 但我懶得打了於是就合併了
當然遇到最短路 卡SPFA注意啦 然後我有魔改SPFA(用dij的思想的=-=) 完全不怕!好吧就是加堆啦 = =
其實原本這堆超醜的 如下
inline void push(int p,int k)
{
++tot;
heap[tot][0] = p;
heap[tot][1] = k;
o[p][k] = 1;
int now = tot;
while (now > 1 && dis[heap[now][0]][heap[now][1]] < dis[heap[now >> 1][0]][heap[now >> 1][1]])
swap(heap[now],heap[now >> 1]),now >>= 1;
}
inline void pop(int &p,int &k)
{
p = heap[1][0];
k = heap[1][1];
o[p][k] = 0;
heap[1][0] = heap[tot][0];
heap[1][1] = heap[tot][1];
--tot;
int now = 1;
while (now << 1 <= tot && dis[heap[now][0]][heap[now][1]] > dis[heap[now << 1][0]][heap[now << 1][1]] ||
now << 1 < tot && dis[heap[now][0]][heap[now][1]] > dis[heap[now << 1 | 1][0]][heap[now << 1 | 1][1]])
{
int nxt = now << 1;
if (nxt < tot && dis[heap[nxt | 1][0]][heap[nxt | 1][1]] < dis[heap[nxt][0]][heap[nxt][1]]) ++nxt;
swap(heap[now],heap[nxt]);
}
}
然後中間判斷距離的就放judge裏面了 看起來好多了 下放代碼
#include <algorithm>
#include <cstring>
#include <cstdio>
#define MAXN 10010
#define MAXM 100010
using namespace std;
struct edge {
int ne,to,v;
} e[MAXM];
struct queue {
int nod,ed;
} heap[MAXM];
int first[MAXN],dis[MAXN][22];
int tot;
short o[MAXN][22];
inline short judge(queue x,queue y) {return dis[x.nod][x.ed] > dis[y.nod][y.ed];}
inline int r()
{
char q = getchar(); int x = 0,y = 0;
while (q < '0' && q != '-' || q > '9') q = getchar();
if (q == '-') ++ y,q = getchar();
while ('0' <= q && q <= '9')
x = (x << 3) + (x << 1) + q - (3 << 4),q = getchar();
return y ? -x : x;
}
inline void add(int x,int y,int z)
{
e[++tot].ne = first[x];
e[tot].to = y;
e[tot].v = z;
first[x] = tot;
}
inline void push(int p,int k)
{
heap[++tot].ed = k;
heap[tot].nod = p;
o[p][k] = 1;
int now = tot;
while (now > 1 && judge(heap[now >> 1],heap[now]))
swap(heap[now],heap[now >> 1]),now >>= 1;
}
inline void pop(int &p,int &k)
{
p = heap[1].nod;
k = heap[1].ed;
o[p][k] = 0;
heap[1] = heap[tot--];
int now = 1;
while (now << 1 <= tot && judge(heap[now],heap[now << 1]) ||
now << 1 < tot && judge(heap[now],heap[now << 1 | 1]))
{
int nxt = now << 1;
if (nxt < tot && judge(heap[nxt],heap[nxt | 1])) ++nxt;
swap(heap[now],heap[nxt]),now = nxt;
}
}
int main()
{
int n = r(),m = r(),k = r(),s = 1,t = n,x,y,z;
while (m--) x = r(),y = r(),z = r(),add(x,y,z),add(y,x,z);
memset(dis,0x7f,sizeof(dis));
tot = 0;
dis[s][0] = 0;
push(s,0);
while (tot)
{
int p,ed;
pop(p,ed);
for (int a = first[p],b = e[a].to ; a ; a = e[a].ne,b = e[a].to)
{
if (dis[p][ed] + e[a].v < dis[b][ed])
{
dis[b][ed] = dis[p][ed] + e[a].v;
if (!o[b][ed]) push(b,ed);
}
if (ed == k) continue;
if (dis[b][ed + 1] > dis[p][ed])
{
dis[b][ed + 1] = dis[p][ed];
if (!o[b][ed + 1]) push(b,ed + 1);
}
}
}
printf("%d\n",dis[t][k]);
return 0;
}
雙倍經驗 這題
三倍經驗 開通我校會員尊享