1 条题解

  • 0
    @ 2026-4-28 22:05:08

    询问不多可以当单次询问做 对于一条A到B的路径,若上面有a条特殊边,他的长度就为ax+b 先将特殊边长视为0,求出f[x][t]表示A到t,走了x条特殊边的最短路 那么A->B=a*x+f[a][B],这些路径的长度对应平面上的若干条直线,a就是这些直线的斜率 如果不存在f[0][B]就有无限种可能值,因为没有上界 否则维护一个凸包就可以求出所有最短路的可能值了

    ———————————————— 版权声明:本文为CSDN博主「L_0_Forever_LF」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/L_0_Forever_LF/article/details/70840234

    #include<set>
    #include<map>
    #include<deque>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<ctime>
    #include<bitset>
    #include<string>
    #include<vector>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<climits>
    #include<complex>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    
    const int maxn = 1100;
    const int maxm = 21000;
    
    int n,m,qn,st,ed;
    
    struct edge
    {
        int xi,y,nex;
        ll c;
    }a[maxm]; int len,fir[maxn];
    inline void ins(const int x,const int y,const ll c,const int xi)
    {
        a[++len].y=y; a[len].c=c; a[len].xi=xi;
        a[len].nex=fir[x]; fir[x]=len;
    }
    
    struct node
    {
        int i,xi;
        ll x;
        node(){}
        node(const int &_x,const int &_i,const int &_xi){x=_x;i=_i;xi=_xi;}
    };
    inline bool operator <(node x,node y){return x.x>y.x;}
    
    priority_queue<node>Q;
    int d[maxn][maxn];
    void search()
    {
        for(int i=1;i<=n;i++) for(int j=0;j<=n;j++) d[i][j]=INT_MAX;
    
        Q.push(node(0,st,0)); d[st][0]=0;
        while(!Q.empty())
        {
            const node x=Q.top(); Q.pop(); 
            if(x.x!=d[x.i][x.xi]) continue;
            for(int k=fir[x.i];k;k=a[k].nex) 
                if(x.xi+a[k].xi<=n&&d[a[k].y][x.xi+a[k].xi]>x.x+a[k].c)
                {
                    d[a[k].y][x.xi+a[k].xi]=x.x+a[k].c;
                    Q.push(node(x.x+a[k].c,a[k].y,x.xi+a[k].xi));
                }
        }
    }
    int q[maxn],tail;
    int sx[maxn];
    void solve()
    {
        int id=-1; 
        for(int i=0;i<=n;i++) if(d[ed][i]!=INT_MAX) {id=i; break;}
        if(id==-1) { puts("0 0"); return; }
        if(id>0) { puts("inf"); return; }
    
        q[tail=1]=0;
        for(int i=1;i<=n;i++) if(d[ed][i]!=INT_MAX)
        {
            if(tail&&d[ed][i]+i>d[ed][q[tail]]+q[tail]) continue;
    
            int ncx=1+(int)((double)(d[ed][q[tail]]-d[ed][i])/(i-q[tail]));
            while(tail>1&&ncx>=sx[tail]) 
            {
                tail--;
                ncx=1+(int)((double)(d[ed][q[tail]]-d[ed][i])/(i-q[tail]));
            }
            q[++tail]=i;
            sx[tail]=ncx;
        }
        ll ans=d[ed][0];
        int now=1,an=1;
        for(int i=tail;i>=2;i--)
        {
            if(i==2&&(sx[i]-1)*q[i]+d[ed][q[i]]==d[ed][0]) sx[i]--;
            an+=sx[i]-now;
            ans+=(ll)(sx[i]-now)*(d[ed][q[i]]+now*q[i]+d[ed][q[i]]+(sx[i]-1)*q[i])/2;
            now=sx[i];
        }
        printf("%d %lld\n",an,ans);
    }
    
    int main()
    {
        char str[110];
    
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int x,y; scanf("%d%d",&x,&y);
            scanf("%s",str);
            if(str[0]=='x') ins(x,y,0,1);
            else
            {
                ll c=0,cl=strlen(str);
                for(int j=0;j<cl;j++) (c*=10)+=str[j]-'0';
                ins(x,y,c,0);
            }
        }
        scanf("%d",&qn);
        while(qn--)
        {
            scanf("%d%d",&st,&ed);
            search();
            solve();
        }
    
        return 0;
    }
    
    • 1

    信息

    ID
    5147
    时间
    1000ms
    内存
    1024MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者