边仙人掌。环上的点全部连向这个环上深度最小的点。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define maxv 500050 #define maxe 1000050 #define inf 0x7f7f7f7f7f7f7f7fLL using namespace std; int n,m,qt,x[maxe],y[maxe],w[maxe],u,v,dep[maxv],anc[maxv][21],g[maxv],deps[maxv]; int id[maxv],bel[maxv],len[maxv],tot=0,pre[maxv],st[maxv],top=0,nume=1,prew[maxv],kr=0; long long dis[maxv]; bool vis[maxv]; struct edge { int v,w,nxt; }e[maxe]; struct data { int a,b; data (int a,int b):a(a),b(b) {} data () {} }; queue <int> q; int read() { char ch;int data=0; while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') { data=data*10+ch-'0'; ch=getchar(); } return data; } void addedge(int u,int v,int w) { e[++nume].v=v;e[nume].w=w;e[nume].nxt=g[u];g[u]=nume; e[++nume].v=u;e[nume].w=w;e[nume].nxt=g[v];g[v]=nume; } void spfa() { for (int i=2;i<=n;i++) dis[i]=inf;dis[1]=0; q.push(1);vis[1]=true;int war=0; while (!q.empty()) { war++; int head=q.front();q.pop(); for (int i=g[head];i;i=e[i].nxt) { int v=e[i].v; if (dis[v]>dis[head]+e[i].w) { dis[v]=dis[head]+e[i].w;dep[v]=dep[head]+1; pre[v]=head;prew[v]=e[i].w; if (!vis[v]) {vis[v]=true;q.push(v);} } } vis[head]=false; } } void dfs(int x) { vis[x]=true; for (int i=g[x];i;i=e[i].nxt) { int v=e[i].v; if (anc[x][0]==v || vis[v]) continue; deps[v]=deps[x]+1;dfs(v); } } void build() { nume=1;memset(g,0,sizeof(g));memset(vis,false,sizeof(vis)); for (int i=1;i<=m;i++) { if (pre[x[i]]==y[i] || pre[y[i]]==x[i]) continue; top=0;tot++; u=x[i];v=y[i]; if (dep[u]<dep[v]) swap(u,v);len[tot]=w[i]; while (dep[u]>dep[v]) {st[++top]=u;bel[u]=1;len[tot]+=prew[u];u=pre[u];} while (u!=v) {st[++top]=u;st[++top]=v;bel[u]=1;bel[v]=2;len[tot]+=prew[u]+prew[v];u=pre[u];v=pre[v];} for (int j=1;j<=top;j++) {anc[st[j]][0]=u;addedge(st[j],u,dis[st[j]]-dis[u]);id[st[j]]=tot;} } for (int i=1;i<=m;i++) { u=x[i];v=y[i]; if (dep[u]>dep[v]) swap(u,v); if (id[u]==id[v] && id[u]) continue; if (id[v] && !id[u]) continue; anc[v][0]=u;addedge(u,v,w[i]); } dfs(1); for (int e=1;e<=20;e++) for (int i=1;i<=n;i++) anc[i][e]=anc[anc[i][e-1]][e-1]; } data lca(int x,int y) { int rx=x,ry=y; for (int e=20;e>=0;e--) { if (deps[anc[x][e]]>=deps[y] && anc[x][e]) x=anc[x][e]; } if (x==y) return data(x,0); for (int e=20;e>=0;e--) { if (anc[x][e]!=anc[y][e]) { x=anc[x][e]; y=anc[y][e]; } } return data(x,y); } long long get_ans(int x,int y) { if (dep[x]>dep[y]) swap(x,y);long long rr,dx,dy; dx=dis[x]-dis[anc[x][0]];dy=dis[y]-dis[anc[y][0]]; if (bel[x]==bel[y]) rr=min(dy-dx,len[id[x]]+dx-dy); else rr=min(dx+dy,len[id[x]]-dx-dy); return rr; } int main() { n=read();m=read();qt=read(); for (int i=1;i<=m;i++) { x[i]=read();y[i]=read();w[i]=read(); addedge(x[i],y[i],w[i]); } spfa(); build(); for (int i=1;i<=qt;i++) { u=read();v=read();if (deps[u]<deps[v]) swap(u,v); data ret=lca(u,v); if (!ret.b) printf("%lld\n",dis[u]-dis[ret.a]); else { if (id[ret.a]==id[ret.b] && id[ret.a]) printf("%lld\n",dis[u]+dis[v]-dis[ret.a]-dis[ret.b]+get_ans(ret.a,ret.b)); else printf("%lld\n",dis[u]+dis[v]-2*dis[anc[ret.a][0]]); } } return 0; }