完结撒花!!!!!!!!!!!
最后一题填坑1A仙人掌WWWWWWW我真流弊
首先把环拆开,环中每一个点连向环的根,然后搞LCA,答案就是套路的d[x]+d[y]-d[lca]*2
然后就可以发现,其实只有当fx和fy在同一个环里面,才有可能通过不同的路线导致答案更小,特判之即可。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<vector> using namespace std; struct node { int x,y,d,next; }a[31000],e[31000];int len,last[11000],elen,elast[11000]; void ins(int x,int y,int d) { len++; a[len].x=x;a[len].y=y;a[len].d=d; a[len].next=last[x];last[x]=len; } void eins(int x,int y,int d) { elen++; e[elen].x=x;e[elen].y=y;e[elen].d=d; e[elen].next=elast[x];elast[x]=elen; } bool edg[11000];int cnt,bel[11000],sum[11000],ts[11000]; int fa[11000],dep[11000],dis[11000]; int tp,id[11000],sdis[11000]; void DP(int rt,int bac) { tp=dep[bac]-dep[rt]+1; for(int i=1;i<=tp;i++) id[tp-i+1]=bac, bac=fa[bac]; sdis[1]=0; for(int i=2;i<=tp;i++) { sdis[i]=sdis[i-1]+dis[id[i]]; ts[id[i]]=sdis[i]; } cnt++;sum[cnt]=sdis[tp]+dis[rt]; for(int i=2;i<=tp;i++) { ins(rt,id[i],min(sdis[i],sum[cnt]-sdis[i])); edg[id[i]]=true; bel[id[i]]=cnt; } } int z,dfn[11000],low[11000]; void cactus(int x) { dfn[x]=low[x]=++z; for(int k=elast[x];k;k=e[k].next) { int y=e[k].y; if(dfn[y]==0) { fa[y]=x; dep[y]=dep[x]+1; dis[y]=e[k].d; cactus(y); low[x]=min(low[x],low[y]); } else if(y!=fa[x]) low[x]=min(low[x],dfn[y]); } for(int k=elast[x];k;k=e[k].next) { int y=e[k].y; if(fa[y]!=x&&dfn[x]<dfn[y]) { int t=dis[x]; dis[x]=e[k].d; DP(x,y); dis[x]=t; } } } //----------------------------------------- int Bin[25]; int f[25][31000]; void dfs(int x) { for(int i=1;dep[x]>=Bin[i];i++)f[i][x]=f[i-1][f[i-1][x]]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=f[0][x]) { f[0][y]=x; dep[y]=dep[x]+1; dis[y]=dis[x]+a[k].d; dfs(y); } } } int LCA(int x,int y,int &fx,int &fy) { int w=-1; if(dep[x]<dep[y]){swap(x,y);w=1;} for(int i=22;i>=0;i--) if(dep[x]-dep[y]>=Bin[i])x=f[i][x]; if(x==y){fx=-1;return x;} for(int i=22;i>=0;i--) if(dep[x]>=Bin[i]&&f[i][x]!=f[i][y])x=f[i][x],y=f[i][y]; if(w==-1)fx=x,fy=y; else fx=y,fy=x; return f[0][x]; } //--------------get_LCA---------------------------- int main() { int n,m,Q,x,y,dd; scanf("%d%d%d",&n,&m,&Q); len=0;memset(last,0,sizeof(last)); elen=0;memset(elast,0,sizeof(elast)); for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&dd); eins(x,y,dd);eins(y,x,dd); } z=cnt=0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(edg,false,sizeof(edg)); fa[1]=0,dep[1]=0,cactus(1); for(int i=2;i<=n;i++) if(edg[i]==false) ins(fa[i],i,dis[i]); Bin[0]=1;for(int i=1;i<=22;i++)Bin[i]=Bin[i-1]*2; f[0][1]=0;dep[1]=0;dis[1]=0;dfs(1); while(Q--) { scanf("%d%d",&x,&y); int fx,fy,lca=LCA(x,y,fx,fy); if(fx!=-1&&bel[fx]!=0&&bel[fx]==bel[fy]) { dd=abs(ts[fx]-ts[fy]); printf("%d ",dis[x]-dis[fx]+dis[y]-dis[fy]+min(dd,sum[bel[fx]]-dd)); } else printf("%d ",dis[x]+dis[y]-2*dis[lca]); } return 0; }