传送门
来一发大常数做法(然而网络赛的时候凸包插点的方向写反了。。。 40 p t s 40pts 40pts滚了什么我居然还有40)
对于一条边 ( u , v , p , q ) (u,v,p,q) (u,v,p,q),我们把二元组 ( v , q ) (v,q) (v,q)看成一个点。
这样下来一共有 m m m个点。
假设每个点对应有 l e n 1 i len1_i len1i个二元组 ( i , v a l 1 i , j ) (i,val1_{i,j}) (i,val1i,j),每个时间点对应有 l e n 2 i len2_i len2i个二元组 ( v a l 2 i , j , i ) (val2_{i,j},i) (val2i,j,i)
然后重新处理每条边。
对于边 ( u , v , p , q ) (u,v,p,q) (u,v,p,q),我们在 u u u对应的时间点中二分出离 q q q最近的 v a l 1 u , t val1_{u,t} val1u,t,建边 ( u , v a l 1 u , t ) → ( v , q ) (u,val1_{u,t})\rightarrow(v,q) (u,val1u,t)→(v,q),如果所有的时间点都比 q q q大就不用建了。
然后我们就建出来了一个 D A G DAG DAG,且如果我们按照时间点为关键字来 f o r for for循环更新最短路的话好像就完了???
恭喜你有 40 p t s 40pts 40pts 因为有40 p t s pts pts的点是不需要建凸包转移其它边的
那么其它边指的是什么边呢?
考虑到我们之间的建图有个 b u g bug bug,那就是 ( u , v a l 1 u , i ≤ t ) (u,val1_{u,i\le t}) (u,val1u,i≤t)全部都可以转移给 ( v , q ) (v,q) (v,q),但是我们只转移了 ( u , v a l 1 u , v a l u , t ) (u,val1_{u,val_{u,t}}) (u,val1u,valu,t)于是凉凉。
直接暴力建边好像复杂度 O ( m 2 ) O(m^2) O(m2)了啊。。。
于是考虑连边 ( u , v a l 1 u , i ) → ( u , v a l 1 u , i + 1 ) (u,val1_{u,i})\rightarrow(u,val1_{u,i+1}) (u,val1u,i)→(u,val1u,i+1)
边权怎么弄???
假设我们现在有这两条边 ( u , a ) → ( u , b ) → ( v , c ) (u,a)\rightarrow(u,b)\rightarrow(v,c) (u,a)→(u,b)→(v,c)
那么本来应该是 ( u , a ) → ( v , c ) a n d ( u , b ) → ( v , c ) (u,a)\rightarrow(v,c)\ and\ (u,b)\rightarrow(v,c) (u,a)→(v,c) and (u,b)→(v,c)
考虑两个之间的差量,不妨设这条边为 ( u , v , t , c ) (u,v,t,c) (u,v,t,c)
那么
( u , a ) → ( v , c ) (u,a)\rightarrow(v,c) (u,a)→(v,c)边权是 A ( c − a ) 2 + B ( c − a ) + C A(c-a)^2+B(c-a)+C A(c−a)2+B(c−a)+C
( u , b ) → ( v , c ) (u,b)\rightarrow(v,c) (u,b)→(v,c)边权是 A ( c − b ) 2 + B ( c − b ) + C A(c-b)^2+B(c-b)+C A(c−b)2+B(c−b)+C
做个差发现差量是 A ( a 2 − b 2 ) + B ( b − a ) + c ∗ ( 2 A ( b − a ) ) A(a^2-b^2)+B(b-a)+c*(2A(b-a)) A(a2−b2)+B(b−a)+c∗(2A(b−a))
很容易把这个结论拓展到多个点的情况。
然后把 c c c看成一个变量,相当于是一堆 A ′ + B ′ c A'+B'c A′+B′c取最小值,这很凸包。
我们把 ( u , b ) (u,b) (u,b)连出去的所有点按照这个 t t t排序,把 ( u , x 1 ) , ( u , x 2 ) , . . . , ( u , b ) (u,x_1),(u,x_2),...,(u,b) (u,x1),(u,x2),...,(u,b)对应的二元组拿来建个凸包就行啦。
代码:
#include
#define ri register int
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
typedef pair<int,int> pii;
typedef pair<int,ll> pil;
typedef pair<ll,ll> pll;
const int N=2e5+5,M=4e5+5,K=1005;
int n,m,A,B,C,tot=0;
struct Node{
int v;pll w;
friend inline bool operator<(const Node&a,const Node&b){return a.w.fi>b.w.fi;}
};
struct edge{int u,v,p,q;}E[M];
Node trans[M<<1];
bool oktrans[M<<1];
ll dis[M<<1];
vector<Node>e[M<<1];
set<int>vis[K],tim[N];
vector<pll>a[M<<1];
typedef set<int>::iterator It;
inline pll operator+(const pll&a,const pll&b){return pll(a.fi+b.fi,a.se+b.se);}
struct pot{
ll x,y;
pot(ll x=0,ll y=0):x(x),y(y){}
friend inline pot operator-(const pot&a,const pot&b){return pot(a.x-b.x,a.y-b.y);}
friend inline ll operator^(const pot&a,const pot&b){return a.x*b.y-a.y*b.x;}
}ap[K<<1];
int top,q[K<<1],mxtim=0;
inline void build(vector<pll>a){
top=0;
int m=a.size();
for(ri i=0;i<m;++i)ap[i+1]=pot(a[i].se,a[i].fi);
for(ri i=1;i<=m;++i){
while(top>1&&((ap[i]-ap[q[top]])^(ap[q[top]]-ap[q[top-1]]))>=0)--top;
q[++top]=i;
}
for(ri i=1;i<=top;++i)ap[i]=ap[q[i]];
}
inline ll calc(pot a,ll b){return a.x*b+a.y;}
inline bool operator<(const pii&a,const pii&b){return a.se>b.se;}
const int mogic=1e6+7;
inline bool operator==(const pii&a,const pii&b){return a.fi==b.fi&&a.se==b.se;}
struct Hash_table1{
vector<pii>ori[mogic];
vector<int>val[mogic];
inline void update(pii x,int c){
int t=(x.fi*1000+x.se)%mogic;
ori[t].push_back(x);
val[t].push_back(c);
}
inline int query(pii x){
int t=(x.fi*1000+x.se)%mogic;
for(ri i=ori[t].size();~i;--i)if(ori[t][i]==x)return val[t][i];
}
}idx;
struct Hash_table2{
vector<int>ori[mogic];
vector<pii>val[mogic];
inline void update(int x,pii c){
int t=x%mogic;
ori[t].push_back(x);
val[t].push_back(c);
}
inline pii query(int x){
int t=x%mogic;
for(ri i=ori[t].size();~i;--i)if(ori[t][i]==x)return val[t][i];
}
}invidx;
bool in[N];
inline void bfs(){
ll ans=1e18;
for(ri i=0;i<=tot;++i)dis[i]=1e18;
dis[1]=0;
static int pre[N];
for(ri tt=0;tt<=mxtim;++tt){
if(!vis[tt].size())continue;
for(It it=vis[tt].begin();it!=vis[tt].end();++it){
pii p=pii(*it,tt);
int id=idx.query(p);
if(p.fi==n){
ans=min(ans,dis[id]+tt);
continue;
}
if(oktrans[id]){
int v=trans[id].v;
pll w=trans[id].w;
if(a[id].size()&&dis[id]<=a[id][0].fi)a[v].push_back(w+pll(dis[id],0));
a[v].push_back(w+pll(dis[id],0));
ri i;
for(i=0;i<a[id].size()&&a[id][i].fi>=dis[id];++i);
for(;i<a[id].size();++i)a[v].push_back(w+a[id][i]);
}
sort(e[id].begin(),e[id].end());
build(a[id]);
for(ri cur=1,i=0,v,P,w;i<e[id].size();++i){
v=e[id][i].v;
P=e[id][i].w.fi;
w=e[id][i].w.se;
if(dis[v]>dis[id]+w)pre[v]=id;
dis[v]=min(dis[v],dis[id]+w);
while(cur<top&&calc(ap[cur],P)>calc(ap[cur+1],P))++cur;
if(top)dis[v]=min(dis[v],calc(ap[cur],P)+w);
}
}
}
cout<<ans<<'\n';
}
signed main(){
n=read(),m=read(),A=read(),B=read(),C=read();
vis[0].insert(1),tim[1].insert(0),idx.update(pii(1,0),tot=1),invidx.update(tot,pii(1,0));
for(ri i=1,u,v,p,q;i<=m;++i){
u=read(),v=read(),p=read(),q=read();
E[i]=(edge){u,v,p,q};
mxtim=max(mxtim,q);
if(!vis[q].count(v))vis[q].insert(v),tim[v].insert(q),++tot,idx.update(pii(v,q),tot),invidx.update(tot,pii(v,q));
}
for(ri u,v,x,y,i=1;i<n;++i){
if(tim[i].size()<2)continue;
for(It il=tim[i].begin(),ir=++tim[i].begin();ir!=tim[i].end();++il,++ir){
x=*il,y=*ir;
u=idx.query(pii(i,x)),v=idx.query(pii(i,y));
trans[u]=(Node){v,pll((ll)B*(y-x)+(ll)A*(x*x-y*y),2ll*A*(y-x))};
oktrans[u]=1;
}
}
for(ri u,v,p,q,i=1;i<=m;++i){
u=E[i].u,v=E[i].v,p=E[i].p,q=E[i].q;
if(!tim[u].size())continue;
It it=tim[u].lower_bound(p);
if(p<*tim[u].begin())continue;
if(it==tim[u].end()||*it>p)--it;
e[idx.query(pii(u,*it))].push_back((Node){idx.query(pii(v,q)),pll(p,(ll)A*(p-*it)*(p-*it)+(ll)B*(p-*it)+(ll)C)});
}
bfs();
return 0;
}