首页 > 代码库 > 值得一做》一道类似于货车运输的题目(BZOJ3732)(easy+)
值得一做》一道类似于货车运输的题目(BZOJ3732)(easy+)
这是一道模板套模板的题目,只要会LCA和最小生成树就可以做,水题
直接先甩题目
Description
给你N个点的无向图 (1 <= N <= 15,000),记为:1…N。
图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000).
现在有 K个询问 (1 < = K < = 15,000)。
每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
Input
第一行: N, M, K。
第2..M+1行: 三个正整数:X, Y, and D (1 <= X <=N; 1 <= Y <= N). 表示X与Y之间有一条长度为D的边。
第M+2..M+K+1行: 每行两个整数A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
Output
对每个询问,输出最长的边最小值是多少。
Sample Input
6 6 8
1 2 5
2 3 4
3 4 3
1 4 8
2 5 7
4 6 2
1 2
1 3
1 4
2 3
2 4
5 1
6 2
6 1
1 2 5
2 3 4
3 4 3
1 4 8
2 5 7
4 6 2
1 2
1 3
1 4
2 3
2 4
5 1
6 2
6 1
Sample Output
5
5
5
4
4
7
4
5
5
5
4
4
7
4
5
HINT
1 <= N <= 15,000
1 <= M <= 30,000
1 <= d_j <= 1,000,000,000
1 <= K <= 15,000
这道题比较困难的是如何想出可行解法,题目中说最大权边最小,而又有很多询问,所以二分答案肯定不行,所以考虑使用一些奇怪的技巧,
我们知道两点之间的这条最大值最小的路径是唯一的,所以我们可以从这方面入手。
显然的,通过一些基本证明,我们可以得知我们要求的实际上是最小生成树,那么既然已经有树形结构了,那么两点之间的路径可以通过LCA轻易的找到,用倍增即可维护最值
直接给出代码
1 #include<stdio.h> 2 #include<algorithm> 3 using namespace std; 4 struct shit{ 5 int aim,from,lon,next; 6 }e[20000],s[61000]; 7 struct ass{ 8 int fat,mx; 9 }f[30][20000];10 int point,dep[20000],fa[20000],fff[20000],cnt,head[20000],n,m,k;11 bool vis[20000];12 int LCA_(int x,int y)13 {14 int mather_fucker=0;15 if(dep[x]>dep[y])swap(x,y);16 for(int i=14;~i;--i)17 if(dep[f[i][y].fat]>=dep[x])18 {19 mather_fucker=max(mather_fucker,f[i][y].mx);20 y=f[i][y].fat;21 }22 if(y==x)return mather_fucker;23 for(int i=15;~i;--i)24 if(f[i][y].fat!=f[i][x].fat){25 mather_fucker=max(mather_fucker,max(f[i][y].mx,f[i][x].mx));26 y=f[i][y].fat;27 x=f[i][x].fat;28 }29 mather_fucker=max(mather_fucker,max(f[0][y].mx,f[0][x].mx));30 return mather_fucker;31 }32 void fuck(int x,int y,int z)33 {34 e[++point].aim=y;e[point].from=x;e[point].lon=z;e[point].next=head[x];head[x]=point;35 e[++point].aim=x;e[point].from=y;e[point].lon=z;e[point].next=head[y];head[y]=point;36 }37 void get(int w,int x,int y,int z)38 {39 s[w].aim=y,s[w].from=x,s[w].lon=z;40 }41 int find(int x)42 {43 return fa[x]==x?x:fa[x]=find(fa[x]);44 }45 bool cmp(shit x,shit y)46 {47 if(x.lon<y.lon)return true;48 else return false;49 }50 void work(int x,int d)51 {52 dep[x]=d;53 vis[x]=true;54 for(int i=head[x];i;i=e[i].next)55 {56 int u=e[i].aim;57 if(vis[u])continue;58 f[0][u].fat=x;59 f[0][u].mx=e[i].lon;60 work(u,d+1);61 }62 }63 int main()64 {65 int a,b,c;66 scanf("%d%d%d",&n,&m,&k);67 for(int i=1;i<=m;i++)68 {69 scanf("%d%d%d",&a,&b,&c);70 get(i,a,b,c);71 }72 for(int i=1;i<=n;i++)fa[i]=i;73 sort(s+1,s+m+1,cmp);74 for(int i=1;i<=m;++i)75 {76 a=find(s[i].aim);77 b=find(s[i].from);78 if(a==b)continue;79 fa[a]=b;80 fuck(a,b,s[i].lon);81 ++cnt;82 if(cnt==n-1)break;83 }84 f[0][n/2].fat=n/2,f[0][n/2].mx=0,dep[n/2]=1,vis[n/2]=true;85 work(n/2,1);86 for(int i=1;i<=15;i++)87 for(int j=1;j<=n;j++)88 {89 f[i][j].fat=f[i-1][f[i-1][j].fat].fat;90 f[i][j].mx=max(f[i-1][j].mx,f[i-1][f[i-1][j].fat].mx);91 }92 for(int i=1;i<=k;++i)93 {94 scanf("%d%d",&a,&b);95 printf("%d\n",LCA_(a,b));96 }97 return 0;98 }
值得一做》一道类似于货车运输的题目(BZOJ3732)(easy+)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。