题解:求树上最短路,所以直接LCA:
倍增求LCA:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 |
#include <cstdio> int f[10010][18]; int s[10010],d[10010],from[10010]; int g[10010],nxt[20010],edv[20010],edw[20010],cnt; bool
vis[10010]; int q,a,b,e,n,m,i,j,x,y,tmp; void
swap( int
&a, int
&b){ int
c=a;a=b;b=c;} void
add( int
u, int v, int w){ edv[++cnt]=v;edw[cnt]=w; nxt[cnt]=g[u];g[u]=cnt; } void
dfs( int
x, int fa, int
fr, int
sum){ from[x]=fr;f[x][0]=fa; vis[x]=1; d[x]=d[fa]+1; s[x]=sum; for ( int
i=g[x];i;i=nxt[i]) if (!vis[edv[i]])dfs(edv[i],x,fr,sum+edw[i]); } int
lca( int
x, int y){ if (x==y) return
x; if (d[x]<d[y])swap(x,y); for ( int
i=17;i>=0;i--) if (d[f[x][i]]>=d[y])x=f[x][i]; if (x==y) return
x; for ( int
i=17;i>=0;i--) if (f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; return
f[x][0]; } int
main(){ while (~ scanf ( "%d%d%d" ,&n,&m,&q)){ for (i=0;i<=10000;i++) for (j=0;j<18;j++) f[i][j]=0; for (i=0;i<=n;i++)vis[i]=from[i]=s[i]=d[i]=g[i]=0; cnt=0; for (i=0;i<m;i++){ scanf ( "%d%d%d" ,&a,&b,&e); add(a,b,e);add(b,a,e); } for (i=1;i<=n;i++) if (!vis[i])dfs(i,0,i,0); for (j=1;j<18;j++) for (i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1]; for (i=0;i<q;i++){ scanf ( "%d%d" ,&x,&y); if (from[x]!=from[y]) puts ( "Not connected" ); else
printf ( "%d\n" ,s[x]+s[y]-2*s[lca(x,y)]); } } return
0; } |
动态树:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 |
#include <cstdio> #include <cstring> #define N 20010 using
namespace std; int f[N],son[N][2],sum[N],data[N],a[N]; bool
rev[N]; inline
void swap( int &a, int &b){ int
c=a;a=b;b=c;} inline
bool isroot( int
x){ return
!f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;} inline
void pb( int
x){ if (rev[x]){ swap(son[x][0],son[x][1]); rev[son[x][0]]^=1;rev[son[x][1]]^=1; rev[x]=0; } } inline
void up( int
x){ sum[x]=data[x]+sum[son[x][0]]+sum[son[x][1]]; } inline
void rotate( int
x){ int
y=f[x]; int
w=(son[y][1]==x); son[y][w]=son[x][w^1]; if (son[x][w^1])f[son[x][w^1]]=y; if (f[y]){ int
z=f[y]; if (son[z][0]==y)son[z][0]=x; if (son[z][1]==y)son[z][1]=x; } f[x]=f[y];son[x][w^1]=y;f[y]=x;up(y); } inline
void splay( int
x){ int
s=1,i=x,y;a[1]=i; while (!isroot(i))a[++s]=i=f[i]; while (s)pb(a[s--]); while (!isroot(x)){ y=f[x]; if (!isroot(y)){ if ((son[f[y]][0]==y)^(son[y][0]==x))rotate(x); else
rotate(y);} rotate(x); } up(x); } inline
void access( int
x){ for ( int
y=0;x;y=x,x=f[x]){ splay(x); son[x][1]=y; up(x); } } inline
int root( int
x){ access(x); splay(x); while (son[x][0])x=son[x][0]; return
x; } inline
void makeroot( int
x){ access(x); splay(x); rev[x]^=1; } inline
void link( int
x, int y){ makeroot(x); f[x]=y; access(x); } inline
int getsum( int
x, int y){ makeroot(x); access(y); splay(x); return
sum[x]; } inline
void read( int &a){ char
ch; while (!((ch= getchar ())>= ‘0‘ )&&(ch<= ‘9‘ )); a=ch- ‘0‘ ; while (((ch= getchar ())>= ‘0‘ )&&(ch<= ‘9‘ ))a*=10,a+=ch- ‘0‘ ; } int
n,m,x,y,c,q; inline
void solve(){ memset (f,0, sizeof
f); memset (son,0, sizeof
son); memset (sum,0, sizeof
sum); memset (data,0, sizeof
data); memset (rev,0, sizeof
rev); read(m);read(q); for ( int
i=1;i<=m;i++){ read(x);read(y);read(c); sum[n+i]=data[n+i]=c; link(x,n+i);link(n+i,y); } while (q--){ read(x);read(y); if (root(x)!=root(y)) puts ( "Not connected" ); else
printf ( "%d\n" ,getsum(x,y)); } } int
main(){ while (~ scanf ( "%d" ,&n))solve(); return
0; } |
HDU 2874 Connections between cities,布布扣,bubuko.com
HDU 2874 Connections between cities
原文:http://www.cnblogs.com/forever97/p/3576853.html