题目链接: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 }