货车运输
题目描述
A国有n座城市,编号从 1到n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入输出格式
输入格式:
第一行有两个用一个空格隔开的整数n,m表示 A 国有n 座城市和 m 条道路。
接下来 m行每行33个整数 x, y, z,每两个整数之间用一个空格隔开,表示从 x号城市到y号城市有一条限重为 zz 的道路。注意: x 不等于 y,两座城市之间可能有多条道路 。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y 。
输出格式:
共有 q行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。
就是每条路径上取一个最小值,有多条路径时取一个最大值,但对每组询问都跑一边SPFA肯定是不对的。
然后看了标签,就是求一个最大生成树,然后用倍增维护最小值......
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 const int maxn=1e4+7; 7 const int maxm=5e4+7; 8 int n,m,num,q,ans,tot; 9 int head[maxn],fa[maxn],dep[maxn],f[maxn][27],imin[maxn][27]; 10 struct E{ 11 int from,to,dis; 12 }e[maxm]; 13 struct Edge{ 14 int next,to,dis; 15 }edge[maxm]; 16 void add(int from,int to,int dis){ 17 edge[++num].next=head[from]; 18 edge[num].to=to; 19 edge[num].dis=dis; 20 head[from]=num; 21 } 22 bool cmp(E a,E b){return a.dis>b.dis;} 23 int find(int x){ 24 if(fa[x]==x) return x; 25 return fa[x]=find(fa[x]); 26 } 27 void merge(int x,int y){ 28 int fx=find(x);int fy=find(y); 29 if(fx!=fy) fa[fx]=fy; 30 } 31 void kruskal(){ 32 int cnt=0; 33 for(int i=1;i<=n;i++) fa[i]=i; 34 for(int i=1;i<=tot;i++){ 35 int u=e[i].from;int v=e[i].to; 36 int fu=find(u);int fv=find(v); 37 if(fu!=fv){ 38 merge(fu,fv);cnt++; 39 add(u,v,e[i].dis);add(v,u,e[i].dis); 40 } 41 if(cnt==n-1) return; 42 } 43 } 44 void prepare(int x,int pre){ 45 dep[x]=dep[pre]+1; 46 for(int i=1;i<=19;i++){ 47 f[x][i]=f[f[x][i-1]][i-1]; 48 imin[x][i]=min(imin[x][i-1],imin[f[x][i-1]][i-1]); 49 } 50 for(int i=head[x];i;i=edge[i].next){ 51 int v=edge[i].to; 52 if(v==pre) continue; 53 f[v][0]=x;imin[v][0]=edge[i].dis; 54 prepare(v,x); 55 } 56 } 57 void process(int x,int y){ 58 int ans1=0x7f7f7f7f;int ans2=0x7f7f7f7f; 59 if(dep[x]<dep[y]) swap(x,y); 60 for(int i=20;i>=0;i--){ 61 if(dep[f[x][i]]>=dep[y]){ans=min(ans1,imin[x][i]);x=f[x][i];} 62 } 63 if(x==y){ans=min(ans1,ans2);return;} 64 for(int i=20;i>=0;i--){ 65 if(f[x][i]!=f[y][i]){ 66 ans1=min(ans1,imin[x][i]);ans2=min(ans2,imin[y][i]); 67 x=f[x][i];y=f[y][i]; 68 } 69 } 70 ans1=min(ans1,imin[x][0]);ans2=min(ans2,imin[y][0]); 71 ans=min(ans1,ans2);return; 72 } 73 int main(){ 74 cin>>n>>m; 75 for(int i=1;i<=n;i++){ 76 int x,y,w;cin>>x>>y>>w; 77 e[++tot].from=x;e[tot].to=y;e[tot].dis=w; 78 } 79 sort(e+1,e+tot+1,cmp); 80 kruskal(); 81 memset(imin,0x7f7f7f7f,sizeof(imin)); 82 prepare(1,0); 83 cin>>q; 84 while(q--){ 85 int x,y;cin>>x>>y; 86 ans=0x7f7f7f7f;process(x,y); 87 if(ans==0x7f7f7f7f) cout<<"-1"<<endl; 88 else cout<<ans<<endl; 89 } 90 return 0; 91 }
上面没有考虑多棵树
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 typedef long long ll; 7 const int maxn=1e4+7; 8 const int maxm=5e4+7; 9 ll n,m,num,q,ans,tot; 10 ll head[maxn],fa[maxn],dep[maxn],f[maxn][27],imin[maxn][27]; 11 struct E{ 12 int from,to,dis; 13 }e[maxm]; 14 struct Edge{ 15 int next,to,dis; 16 }edge[maxm]; 17 void add(int from,int to,int dis){ 18 edge[++num].next=head[from]; 19 edge[num].to=to; 20 edge[num].dis=dis; 21 head[from]=num; 22 } 23 bool cmp(E a,E b){return a.dis>b.dis;} 24 int find(int x){ 25 if(fa[x]==x) return x; 26 return fa[x]=find(fa[x]); 27 } 28 void merge(int x,int y){ 29 int fx=find(x);int fy=find(y); 30 if(fx!=fy) fa[fx]=fy; 31 } 32 void kruskal(){ 33 int cnt=0; 34 for(int i=1;i<=n;i++) fa[i]=i; 35 for(int i=1;i<=tot;i++){ 36 int u=e[i].from;int v=e[i].to; 37 int fu=find(u);int fv=find(v); 38 if(fu!=fv){ 39 merge(fu,fv);cnt++; 40 add(u,v,e[i].dis);add(v,u,e[i].dis); 41 } 42 if(cnt==n-1) return; 43 } 44 } 45 void prepare(int x,int pre){ 46 dep[x]=dep[pre]+1; 47 for(int i=1;i<=19;i++){ 48 if(f[x][i-1]==0) break; 49 f[x][i]=f[f[x][i-1]][i-1]; 50 imin[x][i]=min(imin[x][i-1],imin[f[x][i-1]][i-1]); 51 } 52 for(int i=head[x];i;i=edge[i].next){ 53 int v=edge[i].to; 54 if(v==pre) continue; 55 f[v][0]=x;imin[v][0]=edge[i].dis; 56 prepare(v,x); 57 } 58 } 59 bool process(int x,int y){ 60 ll ans1=0x7f7f7f7f;ll ans2=0x7f7f7f7f; 61 if(dep[x]<dep[y]) swap(x,y); 62 for(int i=20;i>=0;i--){ 63 if(dep[f[x][i]]>=dep[y]){ans1=min(ans1,imin[x][i]);x=f[x][i];} 64 } 65 if(x==y){ans=min(ans1,ans2);return true;} 66 for(int i=20;i>=0;i--){ 67 if(f[x][i]!=f[y][i]){ 68 ans1=min(ans1,imin[x][i]);ans2=min(ans2,imin[y][i]); 69 x=f[x][i];y=f[y][i]; 70 } 71 } 72 if(f[x][0]!=f[y][0]) return false;//因为是取最小值,所以INF会被忽略 73 else{ 74 ans1=min(ans1,imin[x][0]);ans2=min(ans2,imin[y][0]); 75 ans=min(ans1,ans2);return true; 76 } 77 } 78 int main(){ 79 cin>>n>>m; 80 for(int i=1;i<=m;i++){ 81 int x,y,w;cin>>x>>y>>w; 82 e[++tot].from=x;e[tot].to=y;e[tot].dis=w; 83 } 84 sort(e+1,e+tot+1,cmp); 85 kruskal(); 86 memset(imin,0x7f7f7f7f,sizeof(imin)); 87 prepare(1,0);f[1][0]=1; 88 for(int i=1;i<=n;i++){ 89 if(dep[i]==0) {prepare(i,0);f[i][0]=i;} 90 } 91 cin>>q; 92 for(int i=1;i<=q;i++){ 93 int x,y;cin>>x>>y; 94 ans=0x7f7f7f7f; 95 if(!process(x,y)) cout<<"-1"<<endl; 96 else if(ans==0x7f7f7f7f) cout<<"-1"<<endl; 97 else cout<<ans<<endl; 98 } 99 return 0; 100 }