2017.10.24:lca专题系列
商务旅行
题目描述 Description
某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。
假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。
你的任务是帮助该商人计算一下他的最短旅行时间。
输入描述 Input Description
输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。下面N-1行,每行由两个整数a 和b (1<=a, b<=n; a<>b)组成,表示城镇a和城镇b有公路连接。在第N+1行为一个整数M,下面的M行,每行有该商人需要顺次经过的各城镇编号。
输出描述 Output Description
在输出文件中输出该商人旅行的最短时间。
样例输入 Sample Input
5
1 2
1 5
3 5
4 5
4
1
3
2
5
样例输出 Sample Output
7
题解
每两个点之间计算路径长度,累加答案即可。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define maxn 30005 5 using namespace std; 6 int n,m,head[maxn],ecnt,fa[maxn],siz[maxn],deep[maxn],son[maxn],top[maxn],ans; 7 struct edge{ 8 int v,next; 9 }E[maxn<<1]; 10 void add(int u,int v) 11 { 12 E[++ecnt].v=v; 13 E[ecnt].next=head[u]; 14 head[u]=ecnt; 15 } 16 void dfs(int x) 17 { 18 siz[x]=1; 19 for(int i=head[x] ; i ; i=E[i].next ) 20 { 21 int v=E[i].v; 22 if(fa[x]==v)continue; 23 fa[v]=x;deep[v]=deep[x]+1; 24 dfs(v); 25 siz[x]+=siz[v]; 26 if(siz[son[x]]<siz[v])son[x]=v; 27 } 28 } 29 void dfs2(int x,int tp) 30 { 31 top[x]=tp; 32 if(son[x])dfs2(son[x],tp); 33 for(int i=head[x]; i ; i=E[i].next ) 34 { 35 int v=E[i].v; 36 if(son[x]==v||fa[x]==v)continue; 37 dfs2(v,v); 38 } 39 } 40 int lca(int x,int y) 41 { 42 while(top[x]!=top[y]) 43 { 44 if(deep[top[x]]<deep[top[y]])swap(x,y); 45 x=fa[top[x]]; 46 } 47 return deep[x]<deep[y]?x:y; 48 } 49 50 int main() 51 { 52 int u,v,tmp,a; 53 scanf("%d",&n); 54 for(int i=1 ; i<n ; ++i ) 55 { 56 scanf("%d%d",&u,&v); 57 add(u,v);add(v,u); 58 } 59 dfs(1);dfs2(1,1); 60 scanf("%d",&m); 61 scanf("%d",&tmp); 62 for(int i=2 ; i<=m ; ++i ) 63 { 64 scanf("%d",&a); 65 ans+=deep[tmp]+deep[a]-deep[lca(tmp,a)]*2; 66 tmp=a; 67 } 68 printf("%d",ans); 69 return 0; 70 }
bzoj1787:[Ahoi2008]Meet 紧急集合
Input
Output
题解
三个点求lca???不存在的
画个图看一看,不难发现,三点间两两求lca总会有两个lca相同,而且三点到那个lca的距离大于到另外一个lca的距离。
分情况判断就行了
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define maxn 500005 5 using namespace std; 6 int ecnt,head[maxn],siz[maxn],son[maxn],deep[maxn],fa[maxn],top[maxn],n,m; 7 struct edge{ 8 int v,next; 9 }E[maxn<<1]; 10 void add(int u,int v) 11 { 12 E[++ecnt].v=v; 13 E[ecnt].next=head[u]; 14 head[u]=ecnt; 15 } 16 void dfs(int x) 17 { 18 siz[x]=1; 19 for(int i=head[x] ; i ; i=E[i].next ) 20 { 21 int v=E[i].v; 22 if(fa[x]==v)continue; 23 deep[v]=deep[x]+1;fa[v]=x; 24 dfs(v); 25 siz[x]+=siz[v]; 26 if(siz[son[x]]<siz[v])son[x]=v; 27 } 28 } 29 void dfs2(int x,int tp) 30 { 31 top[x]=tp; 32 if(son[x])dfs2(son[x],tp); 33 for(int i=head[x] ; i ; i=E[i].next ) 34 { 35 int v=E[i].v; 36 if(son[x]==v||fa[x]==v)continue; 37 dfs2(v,v); 38 } 39 } 40 int lca(int x,int y) 41 { 42 while(top[x]!=top[y]) 43 { 44 if(deep[top[x]]<deep[top[y]])swap(x,y); 45 x=fa[top[x]]; 46 } 47 return deep[x]<deep[y]?x:y; 48 } 49 inline int read() 50 { 51 int ret(0); 52 char ch=getchar(); 53 while(ch>'9'||ch<'0')ch=getchar(); 54 while(ch>='0'&&ch<='9') 55 { 56 ret=(ret<<1)+(ret<<3)+ch-'0'; 57 ch=getchar(); 58 } 59 return ret; 60 } 61 int main() 62 { 63 int u,v,a,b,c,t1,t2,t3,jud,tmp,fu; 64 n=read();m=read(); 65 for(int i=1 ; i<n ; ++i ) 66 { 67 u=read();v=read(); 68 add(u,v);add(v,u); 69 } 70 dfs(1);dfs2(1,1); 71 while(m--) 72 { 73 a=read();b=read();c=read(); 74 t1=lca(a,b);t2=lca(a,c);t3=lca(b,c); 75 if(t1==t2) 76 { 77 fu=t3; 78 jud=lca(t3,a); 79 tmp=deep[b]+deep[c]+deep[a]-deep[t3]-deep[jud]*2; 80 } 81 if(t2==t3) 82 { 83 fu=t1; 84 jud=lca(t1,c); 85 tmp=deep[b]+deep[c]+deep[a]-deep[t1]-deep[jud]*2; 86 } 87 if(t1==t3) 88 { 89 fu=t2; 90 jud=lca(t2,b); 91 tmp=deep[b]+deep[c]+deep[a]-deep[t2]-deep[jud]*2; 92 } 93 printf("%d %d\n",fu,tmp); 94 } 95 return 0; 96 }