zoukankan      html  css  js  c++  java
  • ACM-ICPC 2018 南京赛区网络预赛 L. Magical Girl Haze (分层dijkstra)

    There are NN cities in the country, and MMdirectional roads from uu to v(1le u, vle n)v(1u,vn). Every road has a distance c_ici. Haze is a Magical Girl that lives in City 11, she can choose no more than KK roads and make their distances become 00. Now she wants to go to City NN, please help her calculate the minimum distance.

    Input

    The first line has one integer T(1 le Tle 5)T(1T5), then following TT cases.

    For each test case, the first line has three integers N, MN,M and KK.

    Then the following MM lines each line has three integers, describe a road, U_i, V_i, C_iUi,Vi,Ci. There might be multiple edges between uu and vv.

    It is guaranteed that N le 100000, M le 200000, K le 10N100000,M200000,K10,
    0 le C_i le 1e90Ci1e9. There is at least one path between City 11 and City NN.

    Output

    For each test case, print the minimum distance.

    样例输入

    1
    5 6 1
    1 2 2
    1 3 4
    2 4 3
    3 4 1
    3 5 6
    4 5 2

    样例输出

    3

    题目大意:

    给你n个点编号从1到n,共有m条有向边,问从1到n的最短路,如果有权利使路径上的k条边的花费变为0。

    分层图dijkstra。

    令dis[i][j]为i点使路径上j条边的花费变为0的情况下的最小距离。这样在更新dis数表的时候,遇到一条边,可以考虑用或不用这条边。这样跑dijkstra就可以了。(感觉上建图直接分k+1层也可以)

    dijkstra堆优化算法需要掌握。在边权为正值时,它比spfa速度更稳定(spfa速度会退化)。实际上,这道题就是卡spfa的。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    
    using namespace std;
    
    const int maxn=100000;
    const int maxm=200000;
    const int inf=2000000000;
    
    int to[maxm+10];
    int w[maxm+10];
    int nex[maxm+10];
    int head[maxn+10];
    
    int dis[maxn+10][11];
    struct tnode
    {
        int a,b;
        int dis;
        bool operator<(const tnode& y) const
        {
            return dis>y.dis;
        }
    };
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n,m,k;
            scanf("%d%d%d",&n,&m,&k);
            memset(head,-1,sizeof(head));
            for(int i=0,u,v,c;i<m;i++)
            {
                scanf("%d%d%d",&u,&v,&c);
                to[i]=v;w[i]=c;
                nex[i]=head[u];head[u]=i;
            }
    
            for(int i=1;i<=n;i++)
            {
                for(int j=0;j<=k;j++)
                    dis[i][j]=inf;
            }
            priority_queue<tnode> q;
            dis[1][0]=0;
            q.push((tnode){1,0,0});
            while(!q.empty())
            {
                tnode node=q.top();q.pop();
                int a=node.a,b=node.b,d=node.dis;
                if(d!=dis[a][b])   continue;
                for(int i=head[a];i!=-1;i=nex[i])
                {
                    int u=a,v=to[i],c=w[i];
                    if(dis[v][b]>dis[u][b]+c)
                    {
                        dis[v][b]=dis[u][b]+c;
                        q.push((tnode){v,b,dis[v][b]});
                    }
                    if(b!=k&&dis[v][b+1]>dis[u][b])
                    {
                        dis[v][b+1]=dis[u][b];
                        q.push((tnode){v,b+1,dis[v][b+1]});
                    }
                }
            }
    
            int ans=inf;
            for(int i=0;i<=k;i++)
            {
                ans=min(ans,dis[n][i]);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    【转】ArcGIS 合并要素 Union Dissolve Append Merge
    Linux命令行下编辑常用快捷键
    rpm aid用法
    SUSE 吉祥物图片
    F9初装体验
    openSUSE10、SUSE EVAL10和SUSE10的区别[翻译]
    装有Linux DIY牛人百元人民币昂贵甜头液晶一体机
    SUSE10.3恢复GRUB体例
    64位Fedora还挑CPU
    Ubuntu8.04安置XCrysDen
  • 原文地址:https://www.cnblogs.com/acboyty/p/9652984.html
Copyright © 2011-2022 走看看