【bzoj2763】[JLOI2011]飞行路线

来源:互联网 发布:win7无法保存网络密码 编辑:程序博客网 时间:2024/04/29 20:40

[JLOI2011]飞行路线

n个点,m条双向边,k次免费的机会,问最短路。
数据范围:2<=n<=10000,1<=m<=50000,0<=k<=10.
时限是10s,但这是所有测试点的总时间。

Sample Input
5 6 1

0 4

0 1 5

1 2 5

2 3 5

3 4 5

2 3 3

0 2 100

Sample Output
8

好久没发博客了有一点不会写了如有不好请指出!!
这道题我用spfa,当然是卡时间过得
将d变成二维表示到第i个点用j次免费次数。
然后的,就和模板spfa接近一样。
只用分两种情况(免费和不免费)
上代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct node{    int x,y,c,next;}a[210000];int len,last[211000];void ins(int x,int y,int c){    len++;    a[len].x=x;a[len].y=y;a[len].c=c;    a[len].next=last[x];last[x]=len;}bool v[111100][11];int d[111000][11];int list[111000][11];int head,tail;int s,e,n,m,kk;void spfa(){    memset(v,true,sizeof(v));v[s][0]=false;    list[1][0]=s;list[1][1]=0;    memset(d,31,sizeof(d));    d[s][0]=0;    head=1,tail=2;    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(d[x][c]+a[k].c<d[y][c])//不免费            {                d[y][c]=d[x][c]+a[k].c;                if(v[y][c])                {                    v[y][c]=false;                    list[tail][0]=y;list[tail][1]=c;                    tail++;                    if(tail==100000+1) tail=1;                }            }            if(d[x][c]<d[y][c+1]&&c<kk)//要免费            {                d[y][c+1]=d[x][c];                if(v[y][c+1])                {                    v[y][c+1]=false;                    list[tail][0]=y;list[tail][1]=c+1;                    tail++;                    if(tail==100000+1) tail=1;                }            }        }        v[x][c]=true;        head++;        if(head==100000+1) head=1;    }}int main(){    scanf("%d%d%d",&n,&m,&kk);    scanf("%d%d",&s,&e);    for(int i=1;i<=m;i++)    {        int x,y,c;        scanf("%d%d%d",&x,&y,&c);        ins(x,y,c);        ins(y,x,c);    }    spfa();    int s=99999999;    for(int i=0;i<=kk;i++)s=min(s,d[e][i]);    printf("%d\n",s);    return 0;}
1 0