Description
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
Input
第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。
接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。
Output
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。
Sample Input
4 3 1 2 4 2 3 3 3 1 1 3 1 3 1 4 1 3
Sample Output
3 -1 3
HINT
对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q < 1,000;
对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q < 1,000;
对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q < 30,000,0 ≤ z ≤ 100,000。
题解: lca就不细说了。
①用并查集维护一个数组fc[i],表示i点到其当前祖先路线中的最长路径,find函数压缩路径时顺便维护。
②利用tarjan并查集求每个询问的lca,在lca处加一个链表,每个询问a->b都有a到lca中的最长路,b到lca的最长路,取大值作为询问的解。
代码:
#include<stdio.h> #include<string.h> #include<stdlib.h> #define N 100100 #define min(a,b) ((a)<(b)?(a):(b)) typedef struct KSD { int u,v,next,l; }ksd;ksd e[N],eq[N],el[N]; int head[N],headq[N],headl[N]; void add(int note,int u,int v,int l){e[note].u=u;e[note].v=v;e[note].l=l;e[note].next=head[u];head[u]=note;} void addq(int note,int u,int v){eq[note].u=u;eq[note].v=v;eq[note].next=headq[u];headq[u]=note;} void addl(int note,int u,int v){el[note].u=u;el[note].v=v;el[note].next=headl[u];headl[u]=note;} int n,m,p; int f[N],fa[N],fl[N],back[N],visit[N];//祖先,父亲,到祖先距离,到父亲距离,是否遍历完子节点 int used[N];//已经dfs过 void init() { int i; for(i=1;i<=n;i++)f[i]=i; memset(head,-1,sizeof(head)); memset(headq,-1,sizeof(headq)); memset(headl,-1,sizeof(headl)); memset(eq,-1,sizeof(eq)); memset(fl,0x3f,sizeof(fl)); } int find(int x) { int t=f[x]; if(f[x]==x)return x; f[x]=find(f[x]); fl[x]=min(fl[x],fl[t]); return f[x]; } void tjlca(int x,int p)//tarjanlca { int i,t,v,fv,tt; used[x]=1; for(t=head[x];t!=-1;t=e[t].next) { v=e[t].v; if(v==p)continue; fa[v]=x; back[v]=e[t].l; tjlca(v,x); } for(t=headq[x];t!=-1;t=eq[t].next) { v=eq[t].v; if(visit[v]==1) { fv=find(v); tt=(t+1)/2*2; eq[tt].l=fl[v]; addl(tt,fv,x); } } for(t=headl[x];t!=-1;t=el[t].next) { v=el[t].v; find(v); eq[t].l=min(eq[t].l,fl[v]); } f[x]=p; fl[x]=back[x]; visit[x]=1; } ksd road[N]; int cnt; int cmp(const void *a,const void*b){return (*(ksd *)b).l-(*(ksd *)a).l;} void Kruskal() { int i,j,k; int fa,fb; for(i=1;i<=m;i++)scanf("%d%d%d",&road[i].u,&road[i].v,&road[i].l); qsort(road+1,m,sizeof(road[1]),cmp); for(i=1;i<=m;i++) { fa=find(road[i].u); fb=find(road[i].v); if(fa!=fb) { cnt++; f[fa]=fb; add(cnt*2-1,road[i].u,road[i].v,road[i].l); add(cnt*2,road[i].v,road[i].u,road[i].l); } if(cnt+1==n)return ; } } int main() { //freopen("test.txt","r",stdin); int i,j,k; int a,b,c; scanf("%d%d",&n,&m); init(); Kruskal(); for(i=1;i<=n;i++)f[i]=i; scanf("%d",&p); for(i=1;i<=p;i++) { scanf("%d%d",&a,&b); addq(i*2-1,a,b); addq(i*2,b,a); } for(i=1;i<=n;i++) { if(used[i]==0) { tjlca(i,i); memset(visit,0,sizeof(visit)); } } for(i=1;i<=p;i++)printf("%d\n",eq[i*2].l); return 0; }