HDU 4725 The Shortest Path in Nya Graph(SPFA)

发现SPFA真的是差不多可以用在大多数的最短路问题上了

就连10的5次方也可以500ms过~

超级好用的算法~~

然后发现数组的大小开的真的很关键,大了MLE,小了就超时。。血的教训

还是很奇怪的是inf = 0x3f3f3f3f 少了一个3f就会出错,真是奇怪!! 

最后就是读题目啊啊啊真的是要理解题意,~~~~

这道题大概就是每个点都属于某一层,相邻的层的点可以以c的value相通,后面再给出其他可以互通的M条边

怎么建图~是个问题。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

const int inf = 0x3f3f3f3f;
const int maxn = 200005;
int Left[maxn*20],Right[maxn*20],key[maxn*20],Next[maxn*20],n,m,c,num[maxn],cnt;
int dict[maxn];
bool vis[maxn],vv[maxn];

void init() {
    cnt = 0;
    memset(vis,false,sizeof(vis));
    memset(Left,-1,sizeof(Left));
    memset(vv,false,sizeof(vv));
}

void add(int u,int v,int value) {
    key[cnt] = value;
    Next[cnt] = Left[u];
    Left[u] = cnt;
    Right[cnt] = v;
    cnt++;
}
queue<int> q;

void SPFA() {
    memset(dict,inf,sizeof(dict));
    dict[1] =0;
    vis[1] = true;
    while(!q.empty()) q.pop();
    q.push(1);
    while(!q.empty()) {
        int temp = q.front();
        q.pop();
        vis[temp] = false;
        for(int i = Left[temp];i != -1;i = Next[i]) {
            if(dict[Right[i]] > dict[temp] + key[i]) {
                dict[Right[i]] = dict[temp] + key[i];
                if(!vis[Right[i]]) {
                    //printf("%d-\n",Right[i]);
                    vis[Right[i]] = true;
                    q.push(Right[i]);
                }
            }
        }
    }
    if(dict[n] >= inf) {
        printf("-1\n");
        return ;
    }
    printf("%d\n",dict[n]);
    return ;
}

int main() {
    //freopen("heiheihei.txt","r",stdin);
    int T;
    scanf("%d",&T);
    for(int l = 1;l <= T;l++) {
        scanf("%d%d%d",&n,&m,&c);
        init();
        int u;
        for(int i = 1;i <= n;i++)
        {
            scanf("%d",&u);
            num[i]=u;
            vv[u]=1;
        }
        for(int i = 1;i < n;i++)
        {
            if(vv[i] && vv[i+1])         
            {
                add(n+i,n+i+1,c);
                add(n+i+1,n+i,c);
            }
        }
        for(int i = 1;i <= n;i++)     
        {
            add(n+num[i],i,0);
            if(num[i] > 1) add(i,n+num[i]-1,c);
            if(num[i] < n) add(i,n+num[i]+1,c);
        }
        for(int i = 1;i <= m;i++) {
            int v,value;
            scanf("%d%d%d",&u,&v,&value);
            add(u,v,value);
            add(v,u,value);
        }
        printf("Case #%d: ",l);
        SPFA();
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值