要求每两个点间的最短路,乍一看卧槽这怎么搞!
乱搞。
注意到m<=n+20,很显然要扯到生成树上。
造一棵树,再将非树边加进来(这咋加啊)
以每条非树边的端点为起点跑最短路,统计答案时取树上和非树上的最短距离就好
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n,m,cnt,tot,q,id; 7 int head[100005]; 8 int dep[100005]; 9 int fa[100005]; 10 int la[100005]; 11 long long dis[100005]; 12 int grand[100005]; 13 int son[100005]; 14 long long ans[100005]; 15 bool mrk[200005]; 16 int siz[100005]; 17 bool usd[100005]; 18 bool vis[100005]; 19 long long len[45][100005]; 20 int findfa(int x){ 21 if(fa[x]==x)return x; 22 return fa[x]=findfa(fa[x]); 23 } 24 struct Query{ 25 int u; 26 int v; 27 }qry[100005]; 28 struct Edge{ 29 int fr; 30 int to; 31 int val; 32 int nxt; 33 }edge[210005]; 34 struct node{ 35 int u; 36 long long w; 37 node(int u,long long w):u(u),w(w){} 38 }; 39 bool operator<(node a,node b){ 40 return a.w>b.w; 41 } 42 void init(){ 43 memset(head,-1,sizeof(head)); 44 memset(len,0x3f,sizeof(len)); 45 } 46 void buildtree(){ 47 for(int i=1;i<=cnt;i+=2){ 48 int u=edge[i].fr; 49 int v=edge[i].to; 50 int fu=findfa(u); 51 int fv=findfa(v); 52 if(fu==fv)continue; 53 fa[fv]=fu; 54 tot++;mrk[i]=mrk[i+1]=true; 55 if(tot==n-1)return; 56 } 57 } 58 void addedge(int u,int v,int w){ 59 cnt++; 60 edge[cnt].fr=u; 61 edge[cnt].to=v; 62 edge[cnt].val=w; 63 edge[cnt].nxt=head[u]; 64 head[u]=cnt; 65 } 66 void dfs1(int u){ 67 siz[u]=1;son[u]=0; 68 for(int i=head[u];i!=-1;i=edge[i].nxt){ 69 if(!mrk[i])continue; 70 int v=edge[i].to; 71 if(v==la[u])continue; 72 la[v]=u;dep[v]=dep[u]+1; 73 dis[v]=dis[u]+edge[i].val; 74 dfs1(v); 75 siz[u]+=siz[v]; 76 if(siz[v]>siz[son[u]])son[u]=v; 77 } 78 } 79 void dfs2(int u){ 80 if(son[la[u]]!=u)grand[u]=u; 81 else grand[u]=grand[la[u]]; 82 for(int i=head[u];i!=-1;i=edge[i].nxt){ 83 if(!mrk[i])continue; 84 int v=edge[i].to; 85 if(v==la[u])continue; 86 dfs2(v); 87 } 88 } 89 int lca(int u,int v){ 90 while(grand[u]!=grand[v]){ 91 if(dep[grand[u]]<dep[grand[v]]){ 92 swap(u,v); 93 } 94 u=la[grand[u]]; 95 } 96 if(dep[u]>dep[v])swap(u,v); 97 return u; 98 } 99 void dijk(int u){ 100 id++;len[id][u]=0; 101 memset(vis,0,sizeof(vis)); 102 priority_queue<node>que; 103 que.push(node(u,0)); 104 while(!que.empty()){ 105 node s=que.top(); 106 que.pop(); 107 if(vis[s.u])continue; 108 vis[s.u]=true; 109 for(int i=head[s.u];i!=-1;i=edge[i].nxt){ 110 int v=edge[i].to; 111 if(len[id][v]>len[id][s.u]+edge[i].val){ 112 len[id][v]=len[id][s.u]+edge[i].val; 113 que.push(node(v,len[id][v])); 114 } 115 } 116 } 117 } 118 int main(){ 119 init(); 120 scanf("%d%d",&n,&m); 121 for(int i=1;i<=n;i++){ 122 fa[i]=i; 123 } 124 for(int i=1;i<=m;i++){ 125 int u,v,w; 126 scanf("%d%d%d",&u,&v,&w); 127 addedge(u,v,w); 128 addedge(v,u,w); 129 } 130 buildtree(); 131 for(int i=1;i<=cnt;i+=2){ 132 int u=edge[i].fr; 133 int v=edge[i].to; 134 if(!mrk[i]){ 135 if(!usd[u]){ 136 dijk(u); 137 usd[u]=true; 138 } 139 if(!usd[v]){ 140 dijk(v); 141 usd[v]=true; 142 } 143 } 144 } 145 dis[1]=0;dep[1]=1; 146 dfs1(1);dfs2(1); 147 scanf("%d",&q); 148 for(int i=1;i<=q;i++){ 149 scanf("%d%d",&qry[i].u,&qry[i].v); 150 int f=lca(qry[i].u,qry[i].v); 151 ans[i]=dis[qry[i].u]+dis[qry[i].v]-dis[f]*2; 152 for(int j=1;j<=id;j++){ 153 ans[i]=min(ans[i],len[j][qry[i].u]+len[j][qry[i].v]); 154 } 155 } 156 for(int i=1;i<=q;i++){ 157 printf("%lld ",ans[i]); 158 } 159 return 0; 160 }