HDU 6071 Lazy Running

题目:http://acm.hdu.edu.cn/showproblem.php?pid=6071

题意:给你4个点,1-2,2-3,3-4,4-1之间有边相连

求从2点出发,回到2点时最接近k的路径长度

取与2相连的最短边w

如果存在一条回到2的路径长度为x,那么一定存在一条长度为x+2w的路径,往返一次就行了

用d[i][j]表示,到达i 时,mod 2*w 为j 时的最短路径

用最短路算法维护这个数组即可

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long ll;
typedef pair<ll,int> pa;
const ll INF=0x3f3f3f3f3f3f3f3f;
int tot;
int mod;
int to[N],nt[N],val[N],head[N];
ll d[5][N];
void add(int u,int v,int w)
{
    nt[++tot]=head[u];
    to[tot]=v;
    val[tot]=w;
    head[u]=tot;
}
void dij(int x)
{
    for(int i=1;i<=4;i++)
        for(int j=0;j<mod;j++)
            d[i][j]=INF;
    priority_queue<pa,vector<pa>,greater<pa> > que;
    que.push(make_pair(0,x));
    while(!que.empty())
    {
        pa t=que.top();que.pop();
        ll x=t.first;
        int y=t.second;
        if (x>d[y][x%mod]) continue;
        for(int i=head[y];i!=-1;i=nt[i])
        {
            ll tem=x+val[i];
            if (d[to[i]][tem%mod]>tem)
            {
                d[to[i]][tem%mod]=tem;
                que.push(make_pair(tem,to[i]));
            }
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll k;
        int d1,d2,d3,d4;
        scanf("%lld%d%d%d%d",&k,&d1,&d2,&d3,&d4);
        if (d1>d2) mod=2*d2;else mod=2*d1;
        tot=0;
        memset(head,-1,sizeof(head));
        add(1,2,d1);add(2,1,d1);
        add(2,3,d2);add(3,2,d2);
        add(3,4,d3);add(4,3,d3);
        add(4,1,d4);add(1,4,d4);
        dij(2);
        ll ans=INF;
        for(int i=0;i<mod;i++)
        {
            if (d[2][i]>=k) ans=min(ans,d[2][i]);
            else ans=min(ans,d[2][i]+(k-d[2][i]+mod-1)/mod*mod);
        }
        printf("%lld
",ans);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/bk-201/p/8873267.html