题解:P10652 「ROI 2017 Day 1」前往大都会
Aurora_Borealis_ · · 题解
第一问可以直接最短路,考虑只有最短路上的点能对第二问有影响,所以重构出最短路图,具体地,一条边
考虑原图上的一条链在新图内会被分割成不相干扰的几条路径,所以直接将这些路径看作不同路径重新编号,然后可以
#include<bits/stdc++.h>
using namespace std;
namespace Aurora{ void Main(); }
int main(){ return Aurora::Main(),0; }
namespace Aurora{
#define int long long
#define ll long long
#define debug printf("debug\n")
const int N=1e6+5;
int n,m,l[N],Road_Cnt=0,id[N];
ll dis[N];
struct EDGE{ int to;ll c; };
struct Road{ int u,v;ll c; };
vector<Road>r[N],nr[N];
vector<int>cov[N];
namespace Dij{
bool vis[N];
struct node{
int x; ll dis;
friend bool operator < (node A,node B){
return A.dis>B.dis;
}
};
vector<EDGE>G[N];
void Dijkstra(){
priority_queue<node>Q; Q.push({1,0});
memset(dis,0x3f,sizeof(dis)); dis[1]=0;
while(!Q.empty()){
int now=Q.top().x; Q.pop();
if(vis[now]) continue;
vis[now]=1;
for(auto tx:G[now]){
int to=tx.to;
if(dis[to]>dis[now]+tx.c){
dis[to]=dis[now]+tx.c;
if(!vis[to]) Q.push((node){to,dis[to]});
}
}
}
}
}
namespace CalcDP{
ll f[N];
int top[N];
vector<int>st[N];
#define X(i) (dis[i])
#define Y(i) (f[i]+dis[i]*dis[i])
#define K(i) (2*dis[i])
#define Exval(i) (dis[i]*dis[i])
double slope(int i,int j){
return 1.0*(Y(i)-Y(j))/(X(i)-X(j));
}
void DP(){
for(int i=1;i<=n;i++){
int now=id[i];
for(auto pos:cov[now]){
// printf("ID:%d POS:%d\n",i,pos);
while(st[pos].size()>1&&slope(st[pos][st[pos].size()-2],st[pos][st[pos].size()-1])<=1.0*K(now)) st[pos].pop_back();
if(st[pos].size()){
int j=st[pos][st[pos].size()-1];
f[now]=max(f[now],Y(j)-K(now)*X(j)+Exval(now));
}
}
for(auto pos:cov[now]){
while(st[pos].size()>1&&slope(st[pos][st[pos].size()-2],st[pos][st[pos].size()-1])<=slope(st[pos][st[pos].size()-1],now)) st[pos].pop_back();
st[pos].push_back(now);
}
}
}
}
bool cmp(int A,int B){
return dis[A]<dis[B];
}
void Main(){
// freopen("tower_sample4.in","r",stdin);
scanf("%lld%lld",&n,&m);
for(int i=1,lst;i<=m;i++){
scanf("%lld%lld",&l[i],&lst);
for(int j=1;j<=l[i];j++){
int x;ll w;scanf("%lld%lld",&w,&x);
Dij::G[lst].push_back((EDGE){x,w});
r[i].push_back((Road){lst,x,w});
lst=x;
}
}
Dij::Dijkstra();
printf("%lld ",dis[n]);
for(int i=1;i<=m;i++){
for(auto now:r[i]){
if(dis[now.u]+now.c==dis[now.v]) nr[i].push_back(now);
}
r[i].clear();
}
// for(int i=1;i<=m;i++){
// cout<<"ID:"<<i<<"\n"<<"NUM:"<<nr[i].size()<<"\n";
// for(auto now:nr[i]) printf("%d %d %lld\n",now.u,now.v,now.c);
// }
for(int i=1;i<=m;i++){
// cout<<nr[i].size()<<endl;
int lst=0;
for(int j=1;j<nr[i].size();j++){
if(nr[i][j-1].v!=nr[i][j].u){
Road_Cnt++;
for(int k=lst;k<=j-1;k++){
r[Road_Cnt].push_back(nr[i][k]);
cov[nr[i][k].u].push_back(Road_Cnt);
}
cov[nr[i][j-1].v].push_back(Road_Cnt);
lst=j;
}
}
if(nr[i].size()){
Road_Cnt++;
for(int k=lst;k<nr[i].size();k++){
r[Road_Cnt].push_back(nr[i][k]);
cov[nr[i][k].u].push_back(Road_Cnt);
}
cov[nr[i][nr[i].size()-1].v].push_back(Road_Cnt);
}
}
// cout<<"RC:"<<cov[1][0]<<" "<<cov[2][0]<<endl;
// for(int i=1;i<=n;i++){
// printf("dis[%d]:%lld\n",i,dis[i]);
// }
for(int i=1;i<=n;i++) id[i]=i;
sort(id+1,id+n+1,cmp);
CalcDP::DP();
printf("%lld\n",CalcDP::f[n]);
}
}