Lazy Running HDU - 6071 最短路+取模

转载自http://blog.csdn.net/yasola

题目大意:

给你一个由四个节点组成的环,求从节点2出发,回到节点2的不小于k的最短路。

解题思路:

又是一个可能出现无限向下走的题目。面对这种问题有一个比较常见的处理方法就是利用同余。

题目要求的是回路,回路有这样一个性质,任意两个回路可以连接构成一个新的回路。于是任意一个回路就可以表示成x+n*y的形式,其中x和y是两个回路。现在再回到利用同余防止循环,如果我们固定y(代码中用的变量名为m),那么对于任意两个模y同余的x的效果是相同的,我们只需要保留最小的那个即可。

显然时间复杂度和y正相关,那么我们就取满足题意的最小回路作为y,然后利用最短路算法找到所有起点为1的相互关于y不同余的环,更新答案即可。在最短路的过程中,对于每一个点也只需要保留关于y不同余的路径即可。
#include<algorithm>
#include<vector>
#include<cstring>
#include<string>
#include<iomanip>
#include<cstdio>
#include<stack>
#include<iostream>
#include<map>
#include<queue>
#include<cmath>
using namespace std;
#define sf scanf
#define pf printf
#define mem(a,b) memset(a,b,sizeof(a));
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define bug1 puts("bug1");
#define bug2 puts("bug2");
#define bug3 puts("bug3");
#define N 1200
#define M 100020
#define mod 100000
#define ULL unsigned long long
#define LL long long
#define inf 0x3f3f3f3f


const int maxp=60010;
LL k;
LL ans;
LL G[5][5];
bool vis[5][maxp];
LL dist[5][maxp];
struct Node{
    int u;
    LL dis;
    Node(int u,LL d):u(u),dis(d){}
};
int m;
void spfa(int s){
    mem(vis,false);
    mem(dist,inf);
    vis[s][0]=true;
    dist[s][0]=0;
    queue<Node>q;
    q.push(Node(s,0));
    while(!q.empty()){
        int u=q.front().u;
        LL now_dis=q.front().dis;q.pop();
        vis[u][now_dis%m]=false;
        for(int i=-1;i<2;i+=2){
            int v=(u+i+4)%4;
            LL next_dis=now_dis+G[u][v],next_p=next_dis%m;
            if(v==s){
                if(next_dis<k)ans=min(ans,((k-1-next_dis)/m+1)*m+next_dis);
                else ans=min(next_dis,ans);
            }
            if(dist[v][next_p]>next_dis){
                dist[v][next_p]=next_dis;
                if(!vis[v][next_p]){
                    vis[v][next_p]=true;
                    q.push(Node(v,next_dis));
                }
            }
        }
    }
}
//2017年08月04日20:58:12
int main(){
    int T;sf("%d",&T);
    while(T--){
        sf("%lld",&k);
        rep(i,0,3){
            sf("%lld",&G[i][(i+1)%4]);
            G[(i+1)%4][i]=G[i][(i+1)%4];
        }
         m=2*min(G[1][0],G[1][2]);
        ans=((k-1)/m+1)*m;//不小于等于的经典做法
        spfa(1);
        pf("%lld\n",ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值