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