1 条题解
-
0
询问不多可以当单次询问做 对于一条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
- 上传者