BZOJ 1579 [Usaco2009 Feb]Revamping Trails 道路升級:dijkstra 分層圖【將k條邊改為0】

Leohh發表於2017-10-09

題目連結: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 }

 

相關文章