• 分层最短路-2018南京网赛L


    大概题意:

    题意:N个点,M条带权有向边,求将K条边权值变为0的情况下,从点1到点N的最短路。

    拓展:可以改变K条边的权值为x

    做法:把每个点拆成k个点,分别表示还能使用多少次机会,构造新图。

    实际写的时候,不用真的拆点,用dist[i][j]表示从源点出发到点i,免费j条边的最小花费,在dijkstra中维护分层即可,每个节点要存价值,编号,已经用的免费条数。

      1 #include <iostream>
      2 #include <queue>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <cmath>
      6 #include <algorithm>
      7 
      8 using namespace std;
      9 
     10 const int maxm = 200010;  //±ß
     11 const int maxn = 100010; //µã
     12 const int inf = 0x3f3f3f3f;
     13 
     14 struct Edge
     15 {
     16     int to,v,next;
     17 } edge[maxm];
     18 struct node
     19 {
     20     long long val;
     21     int num, h;
     22     node(long long _val=0, int _num=0, int _d=0):val(_val), num(_num),h(_d) {}
     23     bool operator <(const node &tmp) const
     24     {
     25         return val > tmp.val;
     26     }
     27 };
     28 int head[maxn];
     29 int top;
     30 int N, M, K;
     31 long long dis[maxn][15];
     32 bool vis[maxn][15];
     33 long long ans = inf;
     34 void init()
     35 {
     36     memset(head, -1, sizeof(head));
     37     top = 0;
     38     for(int i=0; i<=N; i++)
     39     {
     40         for(int j=0; j<=K; j++)
     41         {
     42             dis[i][j] = inf;
     43             vis[i][j] = false;
     44         }
     45     }
     46     ans = inf;
     47 }
     48 
     49 void addedge(int from, int to, int v)
     50 {
     51     edge[top].to = to;
     52     edge[top].v = v;
     53     edge[top].next = head[from];
     54     head[from] = top++;
     55 }
     56 void dijkstra()
     57 {
     58     priority_queue<node> que;
     59     dis[1][0] = 0;
     60     que.push(node(0, 1, 0));
     61     while(!que.empty())
     62     {
     63         node p = que.top();
     64         que.pop();
     65         int nown = p.num;
     66         int h = p.h;
     67         if(vis[nown][h])
     68             continue;
     69         vis[nown][h] = true;
     70         for(int i=head[nown]; i!=-1; i=edge[i].next)
     71         {
     72             Edge e = edge[i];
     73             if(dis[e.to][h] > dis[nown][h] + e.v)
     74             {
     75                 dis[e.to][h] = dis[nown][h] + e.v;
     76                 que.push(node(dis[e.to][h], e.to, h));
     77             }
     78             //修改的地方
     79             if(dis[e.to][h+1] > dis[nown][h] && h < K)
     80             {
     81                 dis[e.to][h+1] = dis[nown][h];
     82                 que.push(node(dis[nown][h], e.to, h+1));
     83             }
     84         }
     85     }
     86     for(int i=0; i<=K; i++)
     87     {
     88         ans = min(ans, dis[N][i]);
     89     }
     90 }
     91 int main()
     92 {
     93     int T;
     94     scanf("%d",&T);
     95     while(T--)
     96     {
     97         scanf("%d%d%d", &N, &M, &K);
     98         init();
     99         int u, v, c;
    100         for(int i=0; i<M; i++)
    101         {
    102             scanf("%d%d%d", &u, &v, &c);
    103             addedge(u, v, c);
    104         }
    105         dijkstra();
    106         printf("%lld
    ", ans);
    107     }
    108     return 0;
    109 }
  • 相关阅读:
    使用viewpager实现QQ界面切换效果
    实例教程十一:访问通信录中的联系人和添加联系人
    实例教程十四:视频刻录(调用前置摄像头)
    实例教程十二:为应用添加多个Activity与参数传递
    【30篇突击 android】源码统计八
    GIF动画 汇总帖子+实例
    Android ProgressBar 几乎全部的用法
    实例教程十三:拍照
    android NDK 知识汇总
    【原创】oracle中大数据量更新的测试
  • 原文地址:https://www.cnblogs.com/flyuz/p/9573617.html
Copyright © 2020-2023  润新知