标签:node int tp long qy CF1715E Way Home dis
套路题。
先不考虑额外的边跑一次最短路。
然后考虑一下额外的边,单独拿出来转移一次。
式子为 \(dis_u=min\{olddis_v+(u-v)^2,1\leq v \leq n\}\)。
简单的,把凸包建出来,二分最优点转移即可。
也就是做一次斜率优化 \(dp\)。
然后继续跑最短路,最短路可以同时 \(n\) 个节点一起跑。
重复 \(k\) 次。
复杂度 \(O(k(nlogm+nlogn))\)。
#include<cstdio>
#include<algorithm>
#include<cstring>
const int N=100010;
#define ll long long
struct node{
int id;
ll val;
bool operator<(const node &A)const {
return val>A.val;
}
};
struct heap{
node st[N<<1];
int tp;
void push(node x){
st[++tp]=x,std::push_heap(st+1,st+tp+1);
}
void pop(){
std::pop_heap(st+1,st+tp+1),tp--;
}
node top(){
return st[1];
}
}q;
struct edge{
edge*net;int to,c;
}e[N<<1],*tot=e,*head[N];
int n,m,k;
ll dis[N];
int vis[N];
void dij(){
memset(vis,0,sizeof vis);
for(int i=1;i<=n;i++)q.push(node{i,dis[i]});
while(q.tp){
int u=q.top().id;q.pop();
if(vis[u])continue;
vis[u]=1;
for(edge*i=head[u];i;i=i->net)if(dis[u]+i->c<dis[i->to]){
dis[i->to]=dis[u]+i->c;
q.push(node{i->to,dis[i->to]});
}
}
}
long long qx[N],qy[N];
int tp;
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1,u,v,w;i<=m;i++)scanf("%d%d%d",&u,&v,&w),*++tot={head[u],v,w},head[u]=tot,*++tot={head[v],u,w},head[v]=tot;
memset(dis,63,sizeof dis),dis[1]=0;
dij();
for(int i=1;i<=k;i++){
tp=0;
for(int j=1;j<=n;j++){
long long ox=2*j,oy=dis[j]+1ll*j*j;
while(tp>1&&(__int128)(oy-qy[tp])*(qx[tp]-qx[tp-1])<=(__int128)(qy[tp]-qy[tp-1])*(ox-qx[tp]))tp--;
qx[++tp]=ox,qy[tp]=oy;
}
for(int j=1;j<=n;j++){
int l=1,r=tp;
while(l<r){
int mid=l+r>>1;
if(qy[mid+1]-qy[mid]<1ll*j*(qx[mid+1]-qx[mid]))l=mid+1;
else r=mid;
}
dis[j]=1ll*j*j+qy[l]-1ll*j*qx[l];
}
dij();
}
for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
return 0;
}
标签:node,int,tp,long,qy,CF1715E,Way,Home,dis 来源: https://www.cnblogs.com/Qzong/p/16609260.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。