标签:mes ret pre ack 题意 lld 最短路问题 bool space
题意:一张n个点的图,有小路和大路,走大路花费的体力值是wi,如果连续走小路,花费的体力是连续走的小路的wi的和的平方,求1到n的最少花费体力
n <= 500, m <= 1e5
大一第一次考CCF的第四题,当年真的还是个最短路都不会的超级萌萌萌萌新,抄挑战的最短路板子(毒瘤代码)骗个40分的部分分,然后当时还怎么想都不明白怎么做
现在看起来就是裸的最短路各种各样的条件这样那样一下而已了= -。。。
几乎所有单源最短路问题都可以套用d[i]为起点到i点的最短路,这题也一样,如果是小路就记录一下连续走了多长的小路距离,换成新的体力花费然后松弛就行
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #include<vector> 6 #include<queue> 7 #define INF 0x3f3f3f3f 8 #define LL long long 9 #define debug(x) cout << "[" << x << "]" << endl 10 using namespace std; 11 12 const int maxn = 510; 13 struct edge{ 14 int v, id; 15 LL w; 16 edge(int v = 0, LL w = 0, int id = 0): v(v), w(w), id(id){} 17 bool operator < (const edge& a) const{ 18 return w > a.w; 19 } 20 }; 21 vector<edge> e[maxn]; 22 bool vis[maxn]; 23 LL d[maxn], sum[maxn]; 24 25 void dijk(){ 26 memset(d, INF, sizeof d); 27 priority_queue<edge> q; 28 d[1] = 0; 29 q.push(edge(1, 0, 0)); 30 while (!q.empty()){ 31 int u = q.top().v; q.pop(); 32 if (vis[u]) continue; 33 vis[u] = 1; 34 for (int i = 0; i < e[u].size(); i++){ 35 int v = e[u][i].v; 36 LL w = e[u][i].w, cost = 0; 37 if (e[u][i].id == 1){ 38 LL tmp = sum[u]+w; 39 cost = d[u]-sum[u]*sum[u]+tmp*tmp; 40 } 41 else cost = d[u]+w; 42 if (d[v] > cost){ 43 d[v] = cost; 44 if (e[u][i].id == 1) sum[v] = sum[u]+w; 45 else sum[v] = 0; 46 q.push(edge(v, d[v], 0)); 47 } 48 } 49 } 50 } 51 52 int main(){ 53 int n, m, t, a, b; 54 LL c; 55 scanf("%d%d", &n, &m); 56 for (int i = 0; i < m; i++){ 57 scanf("%d%d%d%lld", &t, &a, &b, &c); 58 e[a].push_back(edge(b, c, t)); 59 e[b].push_back(edge(a, c, t)); 60 } 61 dijk(); 62 printf("%lld\n", d[n]); 63 return 0; 64 }
标签:mes ret pre ack 题意 lld 最短路问题 bool space
原文地址:https://www.cnblogs.com/QAQorz/p/9588268.html