題目連結:http://www.lydsy.com/JudgeOnline/problem.php?id=1579
題意:
給你一個無向圖,n個點,m條邊,每條邊有邊權w[i]。
你可以將其中的k(k <= 20)條邊的邊權改為0。
問你從1到n的最短路。
題解:
dis[i][j]表示到達i點,已經改了j次邊權,此時的最短路。
相當於將原圖複製成了k層,每改變一次,就向下走一層。
兩種情況(如果可以變優):
(1)不用變0技能:轉移到dis[dest][j] = dis[now][j] + len
(2)用變0技能:轉移到dis[dest][j+1] = dis[now][j]
還有此題卡spfa,要用dijkstra。
因為dijkstra每次處理的點,最小值都已經確定。
所以第一次now.idx == n的時候,now.dis即為答案。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <queue> 5 #define MAX_N 10005 6 #define MAX_K 25 7 8 using namespace std; 9 10 struct Edge 11 { 12 int dest; 13 int len; 14 Edge(int _dest,int _len) 15 { 16 dest=_dest; 17 len=_len; 18 } 19 Edge(){} 20 }; 21 22 struct Node 23 { 24 int idx; 25 int cnt; 26 int dis; 27 Node(int _idx,int _cnt,int _dis) 28 { 29 idx=_idx; 30 cnt=_cnt; 31 dis=_dis; 32 } 33 Node(){} 34 friend bool operator < (const Node &a,const Node &b) 35 { 36 return a.dis>b.dis; 37 } 38 }; 39 40 int n,m,k; 41 int ans; 42 int dis[MAX_N][MAX_K]; 43 vector<Edge> edge[MAX_N]; 44 priority_queue<Node> q; 45 46 void read() 47 { 48 cin>>n>>m>>k; 49 int a,b,v; 50 for(int i=0;i<m;i++) 51 { 52 cin>>a>>b>>v; 53 edge[a].push_back(Edge(b,v)); 54 edge[b].push_back(Edge(a,v)); 55 } 56 } 57 58 int dijkstra(int start,int dst) 59 { 60 memset(dis,0x3f,sizeof(dis)); 61 q.push(Node(start,0,0)); 62 dis[start][0]=0; 63 while(!q.empty()) 64 { 65 Node now=q.top(); 66 q.pop(); 67 if(now.idx==dst) return now.dis; 68 if(dis[now.idx][now.cnt]<now.dis) continue; 69 for(int i=0;i<edge[now.idx].size();i++) 70 { 71 Edge temp=edge[now.idx][i]; 72 if(dis[temp.dest][now.cnt]>now.dis+temp.len) 73 { 74 dis[temp.dest][now.cnt]=now.dis+temp.len; 75 q.push(Node(temp.dest,now.cnt,dis[temp.dest][now.cnt])); 76 } 77 if(dis[temp.dest][now.cnt+1]>now.dis && now.cnt+1<=k) 78 { 79 dis[temp.dest][now.cnt+1]=now.dis; 80 q.push(Node(temp.dest,now.cnt+1,dis[temp.dest][now.cnt+1])); 81 } 82 } 83 } 84 } 85 86 void solve() 87 { 88 ans=dijkstra(1,n); 89 } 90 91 void print() 92 { 93 cout<<ans<<endl; 94 } 95 96 int main() 97 { 98 read(); 99 solve(); 100 print(); 101 }