AC通道:http://codevs.cn/problem/1519/
[分析]
看到这道题,大家有没有想到一道原题呢?反正我是想到了——NOIP2013货车运输。
一模一样的原题啊,只是最大值变为了最小值,而且还不需要判断是否连通。
只需要先求出原图的最小生成树,然后用倍增法就可以轻松解决本题。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct Node{ int nxt,data,weight; }; struct Edge{ int l,r,weight; }; int n,m,cnt=1,q; Node node[200010]; int head[10010]; int fa[10010]; int rfa[10010][15]; int rmq[10010][15]; int deep[10010]; Edge input[100010]; bool vis[10010]; bool cmp(Edge a,Edge b){ return a.weight<b.weight; } inline int Max(int x,int y){ return x>y?x:y; } void add(int x,int y,int z){ node[cnt].nxt=head[x];node[cnt].data=y;node[cnt].weight=z;head[x]=cnt++; node[cnt].nxt=head[y];node[cnt].data=x;node[cnt].weight=z;head[y]=cnt++; } int find(int x){ int tmp=x,pre; while(tmp!=fa[tmp])tmp=fa[tmp]; while(x!=tmp){ pre=fa[x]; fa[x]=tmp; x=pre; } return tmp; } void merge(int x,int y){ int fx=find(x),fy=find(y); fa[fx]=fy; } void kruskal(){ sort(input+1,input+m+1,cmp); int counts=0,i=0; while(counts<n-1){ i++; if(find(input[i].l)!=find(input[i].r)){ counts++; // printf("%d ,%d ,%d\n",input[i].l,input[i].r,input[i].weight); merge(input[i].l,input[i].r); add(input[i].l,input[i].r,input[i].weight); } } } void dfs(int now,int rrfa,int ju){ // printf("%d %d %d\n",now,head[now],node[head[now]].data); if(rrfa!=-1)deep[now]=deep[rrfa]+1; else deep[now]=1; rfa[now][0]=rrfa; rmq[now][0]=ju; for(int i=1;i<=14;i++){ if(rfa[now][i-1]==-1)break; rfa[now][i]=rfa[rfa[now][i-1]][i-1]; rmq[now][i]=Max(rmq[rfa[now][i-1]][i-1],rmq[now][i-1]); } for(int i=head[now];i;i=node[i].nxt) if(!vis[node[i].data]){ vis[node[i].data]=true; dfs(node[i].data,now,node[i].weight); } } int lca(int x,int y){ if(x==y)return 0; int ans=-1; if(deep[x]<deep[y]){int t=x;x=y;y=t;} if(deep[x]>deep[y]){ int derta=deep[x]-deep[y]; for(int i=0;i<=14;i++) if((1<<i)&derta){ ans=Max(ans,rmq[x][i]); x=rfa[x][i]; } } if(x==y)return ans; for(int i=14;i>=0;i--){ if(rfa[x][i]!=-1&&rfa[y][i]!=-1&&rfa[x][i]!=rfa[y][i]){ ans=Max(ans,rmq[x][i]);ans=Max(ans,rmq[y][i]); x=rfa[x][i];y=rfa[y][i]; } } ans=Max(ans,rmq[x][0]);ans=Max(ans,rmq[y][0]); return ans; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<=m;i++)scanf("%d%d%d",&input[i].l,&input[i].r,&input[i].weight); kruskal(); memset(rfa,-1,sizeof rfa); memset(rmq,-1,sizeof rmq); memset(deep,-1,sizeof deep); vis[1]=true; dfs(1,-1,-1); /* for(int i=1;i<=n;i++){ for(int j=0;j<=14;j++) if(rfa[i][j]!=-1){ printf("(%d,%d) ",rfa[i][j],rmq[i][j]); } printf("\n"); }*/ scanf("%d",&q); for(int i=1;i<=q;i++){ int x,y; scanf("%d%d",&x,&y); // if(find(x)!=find(y))printf("-1\n"); printf("%d\n",lca(x,y)); } return 0; }