A:昔我往矣
lca+dfs序,先做出所有点的dfs序,然后对于每一个询问,以dfs序最小和最大的为两个端点,然后往里面加点相当于加上一条分叉出去的链,用LCA求解即可。
下附代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const ll INF=0X3f3f3f3f3f3f3f3f; 5 int Next[100005],to[100005]; 6 ll len[100005]; 7 int head[50005]; 8 ll tot=0; 9 int dep[50005],f[50005][20]; 10 ll l[50005][20],n,q; 11 int a[10]; 12 int dfn[50005],cnt; 13 struct node{ 14 ll p,l; 15 }; 16 bool cmp(int x,int y){ 17 return dfn[x]<dfn[y]; 18 } 19 inline void add(int a,int b,ll c){ 20 Next[tot]=head[a],to[tot]=b,len[tot]=c; 21 head[a]=tot++; 22 } 23 inline void deal(ll x,ll fa){ 24 dep[x]=dep[fa]+1; 25 for (int i=0; i<=16; i++){ 26 f[x][i+1]=f[f[x][i]][i]; 27 l[x][i+1]=l[x][i]+l[f[x][i]][i]; 28 } 29 for (int i=head[x]; i!=-1; i=Next[i]){ 30 int y=to[i]; 31 if (y==fa) continue; 32 f[y][0]=x; 33 l[y][0]=len[i]; 34 deal(y,x); 35 } 36 } 37 void dfs(int x,int pre){ 38 if (dfn[x]!=0) return; 39 dfn[x]=++cnt; 40 for (int i=head[x]; i!=-1; i=Next[i]){ 41 int y=to[i]; 42 if (y!=pre){ 43 dfs(y,x); 44 } 45 } 46 } 47 inline node lca(int x,int y){ 48 int tmp=x; 49 ll ret=0; 50 if (dep[x]<dep[y]) swap(x,y); 51 for (int i=16; i>=0; i--){ 52 if (dep[f[x][i]]>=dep[y]) { 53 ret+=l[x][i]; 54 x=f[x][i]; 55 } 56 if (x==y) { 57 return {y,ret}; 58 } 59 } 60 for (int i=16; i>=0; i--){ 61 if (f[x][i]!=f[y][i]){ 62 ret=ret+l[x][i]; 63 ret=ret+l[y][i]; 64 x=f[x][i]; 65 y=f[y][i]; 66 } 67 } 68 ret+=l[x][0]+l[y][0]; 69 return {f[x][0],ret}; 70 } 71 int main(){ 72 scanf("%lld",&n); 73 for (int i=0; i<n; i++){ 74 head[i]=-1; 75 } 76 for (int i=1; i<n; i++){ 77 ll a,b,c; 78 scanf("%lld%lld%lld",&a,&b,&c); 79 add(a,b,c); 80 add(b,a,c); 81 } 82 deal(0,-1); 83 scanf("%lld",&q); 84 cnt=0; 85 dfs(0,-1); 86 while (q--){ 87 for (int i=1; i<=5; i++){ 88 scanf("%lld",&a[i]); 89 } 90 sort(a+1,a+6,cmp); 91 node p=lca(a[1],a[5]); 92 ll res=p.l; 93 vector<int> now; 94 now.push_back(a[1]); 95 now.push_back(a[5]); 96 for (int i=2; i<=4; i++){ 97 int maxn=0,pp=0; 98 for (auto j:now){ 99 node p1=lca(a[i],j); 100 if (dep[p1.p]>maxn){ 101 maxn=dep[p1.p]; 102 pp=p1.p; 103 } 104 } 105 res+=lca(pp,a[i]).l; 106 now.push_back(a[i]); 107 } 108 printf("%lld ",res); 109 } 110 return 0; 111 }
B:杨柳依依
对于每组起点终点,bfs求出每个点到他们的最短距离与最短路种数
那么对于每组起点终点,如果一个点到起点终点的最短路之和与起点终点距离相同,说明该点在最短路上,概率加上 起点开始的种数*终点开始的种数/总的最短路种数
下附代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int INF=0X3f3f3f3f; 4 int n,m; 5 int head[5005],Next[80005],to[80005],tot=0; 6 double E[5005]; 7 int cnt[2][5005],d[2][5005],b[5005],q[5005]; 8 void add(int a,int b){ 9 Next[tot]=head[a],to[tot]=b; 10 head[a]=tot++; 11 } 12 void bfs(int s,int cnt[],int d[]){ 13 memset(b,0,sizeof(b)); 14 d[s]=0,cnt[s]=1; 15 int r=1,l=0; 16 q[r]=s; 17 while (l<=r){ 18 int x=q[++l]; 19 if (b[x]) continue; 20 b[x]=1; 21 for (int i=head[x]; i!=-1; i=Next[i]){ 22 int y=to[i]; 23 if (d[y]>d[x]+1){ 24 d[y]=d[x]+1; 25 cnt[y]=cnt[x]; 26 q[++r]=y; 27 } 28 else if (d[y]==d[x]+1){ 29 cnt[y]+=cnt[x]; 30 } 31 } 32 } 33 } 34 int main(){ 35 scanf("%d%d",&n,&m); 36 for (int i=0; i<n; i++) head[i]=-1; 37 for (int i=1; i<=m; i++){ 38 int x,y; 39 scanf("%d%d",&x,&y); 40 add(x,y); 41 add(y,x); 42 } 43 int T; 44 scanf("%d",&T); 45 while (T--){ 46 int st,ed; 47 scanf("%d%d",&st,&ed); 48 memset(cnt,0,sizeof(cnt)); 49 memset(d,INF,sizeof(d)); 50 bfs(st,cnt[0],d[0]); 51 bfs(ed,cnt[1],d[1]); 52 if (d[0][ed]==INF) continue; 53 for (int i=0; i<n; i++){ 54 if (d[0][i]+d[1][i]==d[0][ed]){ 55 E[i]+=1.0*cnt[0][i]*cnt[1][i]/cnt[0][ed]; 56 } 57 } 58 } 59 double maxn=-INF; 60 int pos; 61 for (int i=0; i<n; i++){ 62 if (E[i]>maxn){ 63 maxn=E[i]; 64 pos=i; 65 } 66 } 67 printf("%d ",pos); 68 }