HDU 6071 - 同餘+最短路

 

Lazy Running

 

題意:給你一個由四個節點組成的環,求從節點2出發,回到節點2的不小於k的最短路。i只能跑向i+1或者i-1

思路:
根據限制條件,用鄰接表建圖,可以防止更新時有不合法的情況
因爲要構成迴路,考慮不繞圈,最小是選擇與起點相鄰的兩條邊構成迴路。選擇模數m,應該是min(a[1][0],a[1][2])*2  (下標從0開始)
用Dijkstra更新最短路,在 f[1][0...n]中進行求和。  (還可以參考一下這個思路 分析:ftae

 

 

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <vector>
#define LL long long
#define P pair<LL,int>

using namespace std;

const int maxm=6e4+10,maxn=4;
const LL INF=0x3f3f3f3f3f3f3f3f;
struct Node
{
    int t;
    LL dis;
};
vector<Node> v[maxn];
LL f[maxn][maxm],K,m;

void dijkstra(int s)
{
    priority_queue<P,vector<P>,greater<P> > q;
    for(int i=0;i<maxn;++i)
        for(int j=0;j<=m;++j)
        f[i][j]=INF;
    q.push(P(0,s));
    LL x;int y;
    while(!q.empty())
    {
        x=q.top().first;
        y=q.top().second;
        q.pop();
        if(x>f[y][x%m]) continue;
        for(int i=0;i<v[y].size();++i)
        {
            int t=v[y][i].t;
            LL dis=x+v[y][i].dis;
            if(f[t][dis%m]>dis)
            {
                f[t][dis%m]=dis;
                q.push(P(dis,t));
            }
        }
    }
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int d1,d2,d3,d4;
        scanf("%lld%d%d%d%d",&K,&d1,&d2,&d3,&d4);
        memset(v,0,sizeof(v));
        v[0].push_back(Node{1,d1});
        v[1].push_back(Node{0,d1});
        v[1].push_back(Node{2,d2});
        v[2].push_back(Node{1,d2});
        v[2].push_back(Node{3,d3});
        v[3].push_back(Node{2,d3});
        v[3].push_back(Node{0,d4});
        v[0].push_back(Node{3,d4});
        m=min(d1,d2)*2;
        dijkstra(1);

        LL ans=INF,cnt;
        for(int i=0;i<m;++i)
        {
            cnt=K-f[1][i];
            if(cnt<=0) ans=min(ans,f[1][i]);
            else ans=min(ans,f[1][i]+cnt/m*m+(cnt%m>0?1:0)*m);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章