首页 > 代码库 > 值得一做》一道类似于货车运输的题目(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

Sample Output

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 }
View Code

 

值得一做》一道类似于货车运输的题目(BZOJ3732)(easy+)