luogu 5468 [NOI2019]回家路线 最短路/暴力
这道题的斜率优化也比较简单呀
想写一个 70 pts 算法,结果数据水,直接就切了
最短路:
// luogu-judger-enable-o2 #include<bits/stdc++.h> using namespace std; #define setIO(s) freopen(s".in","r",stdin) #define maxn 300000 #define ll long long struct Node { int x,y,p,q; }nd[maxn]; vector<int>G1[maxn],G2[maxn]; map<int,int>date1[maxn],date2[maxn]; int n,m,A,B,C,cnt1,edges,cnt2; int hd[maxn*10],to[maxn*10],nex[maxn*10]; ll val[maxn*10]; inline void addedge(int u,int v,ll c) { nex[++edges]=hd[u], hd[u]=edges, to[edges]=v,val[edges]=c; } inline ll calc(ll u) { return 1ll*A*u*u + 1ll*B*u + 1ll*C; } int S,T; int inq[maxn*10]; ll dis[maxn*10]; queue<int>Q; inline void spfa() { for(int i=1;i<maxn*10;++i) dis[i]=1000000000000; Q.push(S); inq[S]=1; dis[S]=0; while(!Q.empty()) { int u=Q.front(); Q.pop(); inq[u]=0; for(int i=hd[u];i;i=nex[i]) { int v=to[i]; if(dis[u]+val[i] < dis[v]) { dis[v]=dis[u] + val[i]; if(!inq[v]) { inq[v]=1; Q.push(v); } } } } printf("%lld\n",dis[T]); } int main() { int i,j; // setIO("input"); scanf("%d%d%d%d%d",&n,&m,&A,&B,&C); for(i=1;i<=m;++i) { scanf("%d%d%d%d",&nd[i].x,&nd[i].y,&nd[i].p,&nd[i].q); G1[nd[i].y].push_back(nd[i].q); G2[nd[i].x].push_back(nd[i].p); if(!date2[nd[i].x][nd[i].p]) date2[nd[i].x][nd[i].p]=++cnt2; if(!date1[nd[i].y][nd[i].q]) date1[nd[i].y][nd[i].q]=++cnt1; } for(i=1;i<=m;++i) { addedge(date2[nd[i].x][nd[i].p], date1[nd[i].y][nd[i].q] + cnt2, 0); } int k=0; for(i=1;i<=n;++i) { if(!G1[i].size() || !G2[i].size()) continue; for(j=0;j<G1[i].size();++j) { for(k=0;k<G2[i].size();++k) { if(G1[i][j]>G2[i][k]) continue; addedge(date1[i][G1[i][j]] + cnt2, date2[i][G2[i][k]], calc(G2[i][k] - G1[i][j])); } } } S=0,T=cnt1 + cnt2 +100; for(i=0;i<=1000;++i) if(date2[1][i]) addedge(S, date2[1][i], calc(i)); for(i=0;i<=1000;++i) if(date1[n][i]) addedge(date1[n][i] + cnt2, T, i); spfa(); return 0; }
$O(mt)$ DP (网上说这个做法在现场能切题)
#include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) #define maxn 300001 #define inf 1000000000 using namespace std; int n,m,A,B,C; int f[maxn][1002]; int calc(int t) { return A*t*t+B*t+C; } struct Node{ int x,y,p,q; }nd[maxn]; bool cmp(Node a, Node b) { return a.p < b.p; } int main() { // setIO("input"); int i,j; scanf("%d%d%d%d%d",&n,&m,&A,&B,&C); for(i=1;i<=m;++i) { scanf("%d%d%d%d",&nd[i].x,&nd[i].y,&nd[i].p,&nd[i].q); } sort(nd+1,nd+1+m,cmp); for(i=0;i<=n;++i) for(j=0;j<=1000;++j) f[i][j]=inf; f[1][0]=0; for(i=1;i<=m;++i) { for(j=0;j<=nd[i].p;++j) { if(f[nd[i].x][j]==inf) continue; f[nd[i].y][nd[i].q] = min(f[nd[i].y][nd[i].q], f[nd[i].x][j] + calc(nd[i].p - j)); } } int ans=inf; for(i=0;i<=1000;++i) { ans=min(ans, f[n][i] + i); } printf("%d\n",ans); return 0; }