• BZOJ2763: [JLOI2011]飞行路线


    【传送门:BZOJ2763


    简要题意:

      给出n个点(编号为0~n-1),m条双向边,每条边都有权值,每经过边都要花该边的权值的费用,但是可以免费走k条边,求出从起点到终点的最少花费


    题解:

      SPFA,但要在list中添加一个变量为c,表示使用了多少次免费的机会,然后用二维数组f来记录答案,f[i][j]表示到第i个点用j次免费机会的最少费用


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    struct node
    {
        int x,y,d,next;
    }a[110000];int len,last[51000];
    void ins(int x,int y,int d)
    {
        len++;
        a[len].x=x;a[len].y=y;a[len].d=d;
        a[len].next=last[x];last[x]=len;
    }
    int f[110000][11];
    bool v[110000][11];
    int n,m,kk;int st,ed;
    int list[110000][2];
    void spfa()
    {
        int head=1,tail=2;
        memset(list,0,sizeof(list));
        list[1][0]=st;list[1][1]=0;
        while(head!=tail)
        {
            int x=list[head][0],c=list[head][1];
            for(int k=last[x];k;k=a[k].next)
            {
                int y=a[k].y;
                if(f[x][c]+a[k].d<f[y][c])
                {
                    f[y][c]=f[x][c]+a[k].d;
                    if(v[y][c]==false)
                    {
                        v[y][c]=true;
                        list[tail][0]=y;
                        list[tail][1]=c;
                        tail++;if(tail==100000+1) tail=1;
                    }
                }
                if(f[x][c]<f[y][c+1]&&c<kk)
                {
                    f[y][c+1]=f[x][c];
                    if(v[y][c+1]==false)
                    {
                        v[y][c+1]=true;
                        list[tail][0]=y;
                        list[tail][1]=c+1;
                        tail++;if(tail==100000+1) tail=1;
                    }
                }
            }
            head++;if(head==100000+1) head=1;
            v[x][c]=false;
        }
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&kk);
        scanf("%d%d",&st,&ed);
        for(int i=1;i<=m;i++)
        {
            int x,y,d;
            scanf("%d%d%d",&x,&y,&d);
            ins(x,y,d);ins(y,x,d);
        }
        for(int i=0;i<=n;i++) for(int j=0;j<=kk;j++) f[i][j]=999999999;
        memset(v,false,sizeof(v));v[st][0]=true;
        f[st][0]=0;
        spfa();
        int mmin=999999999;
        for(int i=0;i<=kk;i++) mmin=min(f[ed][i],mmin);
        printf("%d
    ",mmin);
        return 0;
    }

     

  • 相关阅读:
    圆周率的计算与进度条
    Python的使用方法
    Python科学计算库
    linux 命令总结[转]
    如何在 Windows 平台上下載 Android 的源码[转]
    装MSN报错问题解决 无法定位程序输入点except handler4 common 于动态链接库nsvcrt.dll【转】
    编写xorg.conf,简单三行解决ubuntu分辩率不可调的问题【转】
    谁说 Android 手机一定要 root 权限才能截屏?![转]
    给自己的忠告[转]
    lockdir加密bug[转]
  • 原文地址:https://www.cnblogs.com/Never-mind/p/7603476.html
Copyright © 2020-2023  润新知