P1967 货车运输
Posted 小时のblog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1967 货车运输相关的知识,希望对你有一定的参考价值。
题目描述
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入输出格式
输入格式:
输入文件名为 truck.in。
输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道
路。 接下来 m 行每行 3 个整数 x、 y、 z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意: x 不等于 y,两座城市之间可能有多条道路 。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y 。
输出格式:
输出文件名为 truck.out。
输出共有 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。
题目大意:求两点之间路径上最短边的最大值。
题解:
方法一、Kruskal建最大生成树+倍增lca
方法二、Kruskal建最大生成树+树链剖分
方法三、Kruskal重构树+树剖求lca
代码
一、黄学长的
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #define inf 0x7fffffff using namespace std; int n,m,q,cnt,tot,deep[10001],head[10001],f[10001],fa[10001][17],d[10001][17]; bool vis[10001]; struct edge{int x,y,v;}a[50001]; struct e{int next,to,v;}e[20001]; void ins(int u,int v,int w) {e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].v=w;} void insert(int u,int v,int w) {ins(u,v,w);ins(v,u,w);} int find(int x) {return f[x]==x?x:f[x]=find(f[x]);} bool cmp(edge a,edge b) {return a.v>b.v;} void dfs(int x) { vis[x]=1; for(int i=1;i<=16;i++) { if(deep[x]<(1<<i))break; fa[x][i]=fa[fa[x][i-1]][i-1]; d[x][i]=min(d[x][i-1],d[fa[x][i-1]][i-1]); } for(int i=head[x];i;i=e[i].next) { if(vis[e[i].to])continue; fa[e[i].to][0]=x; d[e[i].to][0]=e[i].v; deep[e[i].to]=deep[x]+1; dfs(e[i].to); } } int lca(int x,int y) { if(deep[x]<deep[y])swap(x,y); int t=deep[x]-deep[y]; for(int i=0;i<=16;i++) if((1<<i)&t)x=fa[x][i]; for(int i=16;i>=0;i--) { if(fa[x][i]!=fa[y][i]) {x=fa[x][i];y=fa[y][i];} } if(x==y)return x; return fa[x][0]; } int ask(int x,int f) { int mn=inf; int t=deep[x]-deep[f]; for(int i=0;i<=16;i++) { if(t&(1<<i)) { mn=min(mn,d[x][i]); x=fa[x][i]; } } return mn; } int main() { memset(d,127/3,sizeof(d)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)f[i]=i; for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].v); sort(a+1,a+m+1,cmp); for(int i=1;i<=m;i++) { int x=a[i].x,y=a[i].y; int p=find(a[i].x),q=find(a[i].y); if(p!=q) { f[p]=q; insert(x,y,a[i].v); tot++;if(tot==n-1)break; } } for(int i=1;i<=n;i++)if(!vis[i])dfs(i); 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");continue;} else { int t=lca(x,y); printf("%d\n",min(ask(x,t),ask(y,t))); } } return 0; }
二、
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #define maxn 50005 #define inf 0x7fffffff using namespace std; int n,m,sumedge,cnt,q; int head[maxn],fe[maxn],deep[maxn],wson[maxn],top[maxn]; int fa[maxn],size[maxn],dad[maxn],real[maxn],tpos[maxn]; struct Edge{ int x,y,z,nxt; Edge(int x=0,int y=0,int z=0,int nxt=0): x(x),y(y),z(z),nxt(nxt){} }edge[maxn<<1]; struct E{ int x,y,z; // bool operator < (const E &x)const {return z>x.z;} }e[maxn]; void add(int x,int y,int z){ edge[++sumedge]=Edge(x,y,z,head[x]); head[x]=sumedge; } struct Tree{ int l,r,maxv,minv; }tr[maxn<<2]; int f(int x){ return fa[x]==x?x:fa[x]=f(fa[x]); } bool cmp(E a,E b){ return a.z>b.z; } void Kruskal(){ sort(e+1,e+m+1,cmp); int tot=0; for(int i=1;i<=m;i++){ int fx=f(e[i].x),fy=f(e[i].y); if(fx!=fy){ fa[fx]=fy; add(e[i].x,e[i].y,e[i].z); add(e[i].y,e[i].x,e[i].z); if(++tot==n-1)break; } } } void dfs1(int x,int fu){ size[x]=1; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v==fu)continue; dad[v]=x;fe[v]=edge[i].z;deep[v]=deep[x]+1; dfs1(v,x); size[x]+=size[v]; if(size[v]>size[wson[x]])wson[x]=v; } } void dfs2(int x,int fr){ tpos[x]=++cnt;real[cnt]=x;top[x]=fr; if(wson[x])dfs2(wson[x],fr); for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&v!=wson[x])dfs2(v,v); } } void pushup(int rt){ tr[rt].maxv=max(tr[rt<<1].maxv,tr[rt<<1|1].maxv); tr[rt].minv=min(tr[rt<<1].minv,tr[rt<<1|1].minv); return; } void build(int rt,int l,int r){ tr[rt].l=l;tr[rt].r=r; if(l==r){ tr[rt].minv=tr[rt].maxv=fe[real[l]]; return ; } int mid=(l+r)>>1; build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); pushup(rt); } /*int query_min(int rt,int l,int r,int ql,int qr){ if(l>r)return 2147483647; if(ql<=l&&r<=qr){ return tr[rt].minv; // cout<<"lalal "<<tr[rt].minv<<endl; } int mid=(l+r)>>1;ans=inf; if(qr<=mid)return query_min(rt<<1,l,mid,ql,qr); else if(ql>mid)return query_min(rt<<1|1,mid+1,r,ql,qr); else return min(query_min(rt<<1,l,mid,ql,qr),query_min(rt<<1|1,mid+1,r,ql,qr)); if (ql<=mid)return query_min(rt<<1,l,mid,ql,qr); if (qr>mid)return query_min(rt<<1|1,mid+1,r,ql,qr); } */ int query_min(int o,int l,int r,int ql,int qr){ if (l>r) return 2147483647; int mid=(l+r)/2,ans=inf; if (ql<=l&&r<=qr)return tr[o].minv; if (ql<=mid)ans=min(ans,query_min(o*2,l,mid,ql,qr)); if (qr>mid)ans=min(ans,query_min(o*2+1,mid+1,r,ql,qr)); //pushup(o); return ans; } int qmin(int u,int v){ int ans=inf; while(top[u]!=top[v]){ if(deep[top[u]]>deep[top[v]])swap(u,v); ans=min(ans,query_min(1,1,n,tpos[top[v]],tpos[v])); v=dad[top[v]]; } if(deep[u]>deep[v])swap(u,v); ans=min(ans,query_min(1,1,n,tpos[u]+1,tpos[v])); } int main(){ memset(fe,-1,sizeof(fe));//** scanf("%d%d",&n,&m); for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z); for(int i=1;i<=n;i++)fa[i]=i; Kruskal(); dfs1(1,0); dfs2(1,1); build(1,1,n); scanf("%d",&q); while(q--){ int x,y; scanf("%d%d",&x,&y); if(f(x)!=f(y))printf("-1\n"); else printf("%d\n",qmin(x,y)); } return 0; }
三、
#include<iostream> #include<cstdio> #include<algorithm> #define maxm 500008 #define maxn 100008 using namespace std; int n,m,x,y,z,tot,sumedge,nn,q; int head[maxn],fa[maxn],size[maxn],dad[maxn],top[maxn],deep[maxn],w[maxn]; struct E{ int x,y,z; /// bool operator < (const E &a)const{return z>a.z;} }e[maxm]; struct Edge{ int x,y,nxt; Edge(int x=0,int y=0,int nxt=0): x(x),y(y),nxt(nxt){} }edge[maxn<<1]; void add(int x,int y){ edge[++sumedge]=Edge(x,y,head[x]); head[x]=sumedge; } bool cmp(E a,E b){return a.z>b.z;} int f(int x){return fa[x]==x?x:fa[x]=f(fa[x]);} void dfs(int x){ size[x]=1;deep[x]=deep[dad[x]]+1; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]){ dad[v]=x; dfs(v); size[x]+=size[v]; } } } void dfs2(int x){ int s=0; if(!top[x])top[x]=x; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&size[v]>size[s])s=v; } if(s){ top[s]=top[x]; dfs2(s); } for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&v!=s)dfs2(v); } } int lca(int x,int y){ for(;top[x]!=top[y];){ if(deep[top[x]]>deep[top[y]]) swap(x,y); y=dad[top[y]]; } if(deep[x]>deep[y])swap(x,y); return w[x]; } int main(){ scanf("%d%d",&n,&m);nn=n; for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z); for(int i=1;i<=n;i++)fa[i]=i; sort(e+1,e+m+1,cmp); for(int i=1;i<=m;i++){ int fx=f(e[i].x),fy=f(e[i].y); if(fx!=fy){ nn++; add(nn,fx);add(fx,nn); add(fy,nn);add(nn,fy); fa[nn]=nn;fa[fx]=nn;fa[fy]=nn; ++tot;w[nn]=e[i].z; if(tot==n-1)break; } } dfs(nn);dfs2(nn); scanf("%d",&q); for(int i=1;i<=q;i++){ scanf("%d%d",&x,&y); if(f(x)!=f(y)){ printf("-1\n"); continue; } printf("%d\n",lca(x,y)); } return 0; }
以上是关于P1967 货车运输的主要内容,如果未能解决你的问题,请参考以下文章