BZOJ 1579 [Usaco2009 Feb]Revamping Trails 道路升级:dijkstra 分层图【将k条边改为0】

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

 

posted @ 2017-10-09 14:10  Leohh  阅读(293)  评论(0编辑  收藏  举报