The Shortest Statement,题解
Posted wish-all-ac
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了The Shortest Statement,题解相关的知识,希望对你有一定的参考价值。
题目链接
分析:
还是很明白的题意,直接分析问题,首先,这一题真的是给spfa用武之地,m比n大不超过20,但是这并不能使暴力不t,我们考虑一下如何改进一下,我们这样想,这个图只比它的生成树多最多21条边,而树上的最短路有是那么的容易(lca),我们可以先求出在树上两个点之间的最短路,可是非树边也很有可能通过啊,怎么办呢?我们可以这样想,通过至少一个非树边与只通过树边是对立的,也就是说除了只通过非树边的都通过树边,而只通过树边的很好求,下面我们来思考如何求通过至少一个非树边的路径。
如果通过至少一个非树边,那么一定通过这个边的两个顶点那么就好办了,最多一共有42个顶点在非树边两边,直接枚举通过每一个就好了(当然要提前处理出这些顶点的单元最短路)。
还有,这题spfa好像是比dij快(m-n<=20)。
代码(dij)
#include <cstdio> #include <queue> #include <cstring> using namespace std; const int maxn=1e5+10; struct E{ int to; int next; long long val; int f; E(){ f=0; } }ed[maxn*2]; int head[maxn]; int tot; void J(int a,int b,long long c){ tot++; ed[tot].to=b; ed[tot].val=c; ed[tot].next=head[a]; head[a]=tot; } int vis[maxn]; int t[maxn][21]; long long va[maxn][21]; int js; int a[maxn]; int b[maxn]; long long c[maxn]; int de[maxn]; void Dfs(int x,int fa,int id){ de[x]=de[fa]+1; t[x][0]=fa; va[x][0]=ed[id].val; for(int i=1;i<=20;i++){ t[x][i]=t[t[x][i-1]][i-1]; va[x][i]=va[x][i-1]+va[t[x][i-1]][i-1]; } vis[x]=1; for(int i=head[x];i;i=ed[i].next){ if(ed[i].to==fa||ed[i].f) continue; if(vis[ed[i].to]){ ed[i].f=ed[i%2?(i+1):(i-1)].f=1; js++; a[js]=x; b[js]=ed[i].to; c[js]=ed[i].val; continue; } Dfs(ed[i].to,x,i); } } long long dis[43][maxn]; int vis2[maxn]; int ha; struct Node{ int x; long long dis; Node(){ } Node(int a,long long b){ x=a; dis=b; } friend bool operator < (Node a,Node b){ return a.dis>b.dis; } }; priority_queue<Node> q; void dij(int s){ memset(vis2,0,sizeof(vis2)); ha++; dis[ha][s]=0; q.push(Node(s,0)); while(!q.empty()){ Node js=q.top(); q.pop(); if(vis2[js.x]) continue; vis2[js.x]=1; for(int i=head[js.x];i;i=ed[i].next) if(dis[ha][ed[i].to]>dis[ha][js.x]+ed[i].val){ dis[ha][ed[i].to]=dis[ha][js.x]+ed[i].val; q.push(Node(ed[i].to,dis[ha][ed[i].to])); } } } long long lca(int x,int y){ long long ans=0; if(de[x]<de[y]) swap(x,y); int k=de[x]-de[y]; int ji=0; while(k){ if(k&1){ ans+=va[x][ji]; x=t[x][ji]; } k>>=1; ji++; } if(x==y) return ans; for(int i=20;i>=0;i--) if(t[x][i]!=t[y][i]){ ans+=va[x][i]; ans+=va[y][i]; x=t[x][i]; y=t[y][i]; } ans+=va[x][0]+va[y][0]; return ans; } long long Min(long long a,long long b){ return a>b?b:a; } int main(){ memset(dis,0x3f,sizeof(dis)); int n,m; scanf("%d%d",&n,&m); int js1,js2; long long js3; for(int i=1;i<=m;i++){ scanf("%d%d%lld",&js1,&js2,&js3); J(js1,js2,js3); J(js2,js1,js3); } Dfs(1,0,0); for(int i=1;i<=js;i++){ dij(a[i]); dij(b[i]); } int q; scanf("%d",&q); for(int i=1;i<=q;i++){ scanf("%d%d",&js1,&js2); long long p=lca(js1,js2); for(int j=1;j<=2*js;j++) p=Min(dis[j][js1]+dis[j][js2],p); printf("%lld ",p); } return 0; }
以上是关于The Shortest Statement,题解的主要内容,如果未能解决你的问题,请参考以下文章
题解Luogu CF1051F The Shortest Statement
[CF1051F]The Shortest Statement
CF1051F The Shortest Statement