noip2013货车运输
2016-10-09 17:34
330 查看
LCA初步:noip2013货车运输
描述A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入格式
第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。
接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。
输出格式
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。
样例输入
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
样例输出
3
-1
3
提示
对于 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。
30%就直接爆搜,60%用并查集弄最大生成树后找两个点连接的不同路径中每条路径的最小值的最大值(有点绕……),100%思想和60%一样但需用到LCA
代码:
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; struct node{ int a,b,w; }gg[50005]; int head[10005],tov[20005],ne[20005],w[20005],fat[10005]; int tot,fa[10005][20],dis[10005][18],deep[10005]; bool judge[10005]; void add(int a,int b,int z) { tov[++tot]=b; ne[tot]=head[a]; w[tot]=z; head[a]=tot; } int cmp(const node&a,const node&b) { return a.w>b.w; } int find(int x) { if(x!=fat[x])return fat[x]=find(fat[x]); return fat[x]; } void dfs(int k) { judge[k]=true; for(int i=1;i<=16;i++) { if(deep[k]<(1<<i))break; fa[k][i]=fa[fa[k][i-1]][i-1]; dis[k][i]=min(dis[k][i-1],dis[fa[k][i-1]][i-1]);//这道题条件 } int t=head[k]; while(tov[t]) { if(!judge[tov[t]]) { fa[tov[t]][0]=k; dis[tov[t]][0]=w[t]; deep[tov[t]]=deep[k]+1; dfs(tov[t]); } t=ne[t]; } } int lca(int a,int b) { if(deep[a]<deep[b]) swap(a,b); int t=deep[a]-deep[b]; for(int i=0;i<=16;i++)//16到0也可以 if((1<<i)&t) a=fa[a][i];//只跳二进制数t中有1的位数,保证刚好跳t for(int i=16;i>=0;i--) if(fa[a][i]!=fa[b][i])//不跳过 { a=fa[a][i]; b=fa[b][i]; } if(a==b)return b;//刚好跳到最近公共祖先 return fa[b][0];//刚好跳到最近公共祖先的下一个 } int ask(int x,int y) { int minx=2100000000; int t=deep[x]-deep[y]; for(int i=0;i<=16;i++) { if(t&(1<<i)) { minx=min(minx,dis[x][i]);//算x到y的最小值 x=fa[x][i]; } } return minx; } int main() { int n,m; memset(dis,127/3,sizeof dis); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d%d",&gg[i].a,&gg[i].b,&gg[i].w); sort(gg+1,gg+m+1,cmp); for(int i=1;i<=n;i++) fat[i]=i; int cnt=0; for(int i=1;i<=m;i++) { int x=gg[i].a,y=gg[i].b; x=find(x);y=find(y); if(x!=y)//建最大生成树,两点连通过就不再连 { fat[x]=y; add(gg[i].a,gg[i].b,gg[i].w); add(gg[i].b,gg[i].a,gg[i].w); cnt++; if(cnt==n-1) break; } } for(int i=1;i<=n;i++) if(!judge[i]) dfs(i); int q; scanf("%d",&q); while(q--) { int a,b; scanf("%d%d",&a,&b); if(find(a)!=find(b)) { printf("-1\n"); continue; } int f=lca(a,b); printf("%d\n",min(ask(a,f),ask(b,f))); } return 0; }
相关文章推荐
- NOIP2013货车运输 (最大生成树,分块求LCA)
- [NOIP 2013]货车运输
- NOIP2013day1T3----货车运输(LCA+生成树)
- noip2013 day1-3 货车运输
- noip2013货车运输(lca)
- noip2013 货车运输
- NOIP2013 货车运输 (最大生成树+树上倍增LCA)
- NOIP 2013 货车运输(最大生成树+倍增LCA/Tarjan)
- NOIP 2013 货车运输 题解过程
- Noip2013 货车运输 - 生成树 - 倍增
- 洛谷—— P1967 货车运输 || COGS——C 1439. [NOIP2013]货车运输
- NOIP 2013 货车运输 TYVJ 3115
- 【NOIP 2013】货车运输 倍增+kruskal
- [NOIP2013]货车运输
- 洛谷P1967 [Noip2013]货车运输
- NOIP2013 货车运输 (最大生成树+树上倍增LCA)
- 【NOIP2013】 货车运输
- 洛谷 P1967 [NOIP2013 D1T3] 货车运输
- NOIP2013 货车运输 LCA倍增+最大生成树
- NOIP 2013 货车运输