【NOIP2013】货车运输 最大生成树+LCA

题目描述

AA国有nn座城市,编号从 1n,城市之间有m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

输入输出格式

输入格式:

第一行有两个用一个空格隔开的整数n,m,表示 A 国有 n 座城市和 m 条道路。

接下来 m行每行3个整数 x,y,z,每两个整数之间用一个空格隔开,表示从 xx号城市到yy号城市有一条限重为 z的道路。注意:x 不等于 y,两座城市之间可能有多条道路 。

接下来一行有一个整数 q,表示有 q 辆货车需要运货。

接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y 。

输出格式:

共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1

输入输出样例

输入样例#1:
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
输出样例#1:
3
-1
3

说明

对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q< 1,0000<n<1,000,0<m<10,000,0<q<1,000;

对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q< 1,0000<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,0000<n<10,000,0<m<50,000,0<q<30,000,0z100,000。

--------------------------------------------------------------------

这道题的思路就是先用最大生成树将图跑成一棵新树,然后在跑LCA的时候更新路上的最小值

为什么呢,“我们可以发现有一些权值较小的边是不会被走过的。正如样例中的第三条边,就算有其他的很多条边,这条边无论如何也是不会被走过的。于是我们想到了可以将图中这样的边去掉,按照这个思路我们便想到了构造最大生成树,将其余的边去除。”(来自luogu的大佬

然后我的关注点就变为了如何在LCA上记录最小值呢?

在预处理每个点的父亲的时候 我们用一个相似的f[i][j]数组来记录i跳2^j时的最小边权

注意:LCA在开数组的时候,maxn=20, 则p[N][maxn+5] (这个错查了2h....以后绝对不能再犯了

  1 #include<bits/stdc++.h>
  2 #define N 100010
  3 #define maxn 20
  4 #define INF 0x7f7f7f7f
  5 #define ll long long
  6 using namespace std;
  7 int n,m,q;
  8 struct node
  9 {
 10     int u,v,nxt;
 11     ll w;
 12 }e[N*2],d[N*2];
 13 int first[N],cnt;
 14 void ade(int u,int v,ll w)
 15 {
 16     e[++cnt].nxt=first[u]; first[u]=cnt;
 17     e[cnt].u=u; e[cnt].v=v; e[cnt].w=w;
 18 }
 19 
 20 int fir[N],cnnt;
 21 void adde(int u,int v,ll w)
 22 {
 23     d[++cnnt].nxt=fir[u]; fir[u]=cnnt;
 24     d[cnnt].u=u; d[cnnt].v=v; d[cnnt].w=w;
 25 }
 26 /*-------kruskal---------*/
 27 int fa[N];
 28 int la(int x)
 29 {
 30     if(fa[x]!=x) fa[x]=la(fa[x]);
 31     return fa[x];
 32 }
 33 bool cmp(node a,node b)
 34 {
 35     return a.w>b.w;
 36 }
 37 void kruskal()
 38 {
 39     for(int i=1;i<=n;i++) fa[i]=i;
 40     sort(e+1,e+cnt+1,cmp);
 41     for(int i=1;i<=cnt;i++)
 42     {
 43         int x=la(e[i].u),y=la(e[i].v);
 44         if(x!=y)
 45         {
 46             fa[x]=y;
 47             adde(e[i].u,e[i].v,e[i].w); 
 48             adde(e[i].v,e[i].u,e[i].w);
 49         }
 50     }
 51 //    cout<<"!!!!";
 52 //    for(int i=1;i<=cnnt;i+=2)
 53 //        printf("%d %d %d\n",d[i].u,d[i].v,d[i].w);
 54 //    cout<<"!!!!";
 55 }
 56 
 57 /*-----lca------*/
 58 int dep[N],p[N][maxn+5];
 59 ll val[N][maxn+5];
 60 bool vis[N];
 61 void pre()
 62 {
 63     for(int j=1;j<=maxn;j++)
 64         for(int i=1;i<=n;i++)
 65         {
 66             p[i][j]=p[p[i][j-1]][j-1];
 67             val[i][j]=min(val[i][j-1],val[p[i][j-1]][j-1]);
 68         }
 69 }
 70 void dfs(int u,int fath)
 71 {
 72     vis[u]=1;
 73     dep[u]=dep[fath]+1;
 74     p[u][0]=fath;
 75     for(int i=fir[u];i;i=d[i].nxt)
 76     {
 77         int v=d[i].v;
 78         if(vis[v]) continue;
 79         val[v][0]=d[i].w;
 80         dfs(v,u);
 81     }
 82 }
 83 ll lca(int x,int y)
 84 {
 85     ll minx=INF;
 86     if(dep[x]<dep[y]) swap(x,y);
 87     for(int i=maxn;i>=0;i--)
 88         if(dep[x]-(1<<i)>=dep[y])
 89         {
 90             minx=min(minx,val[x][i]);
 91             x=p[x][i];
 92         }
 93     if(x==y) return minx;
 94     for(int i=maxn;i>=0;i--)
 95         if(p[x][i]!=p[y][i])
 96         {
 97             minx=min( minx, min(val[x][i],val[y][i]) );
 98             x=p[x][i],y=p[y][i];
 99         }
100     minx=min( minx, min(val[x][0],val[y][0]) );
101     return minx;    
102 }
103 /*---------*/
104 int main()
105 {
106     scanf("%d%d",&n,&m);
107     memset(val,INF,sizeof(val));
108     for(int i=1,x,y;i<=m;i++)
109     {
110         ll z;
111         scanf("%d%d%lld",&x,&y,&z);
112         ade(x,y,z);
113     }
114     kruskal();
115     for(int i=1;i<=n;i++)
116         if(!vis[i]) dfs(i,0);
117     pre();
118     scanf("%d",&q);
119     while(q--)
120     {
121         int x,y;
122         scanf("%d%d",&x,&y);
123         if(la(x)!=la(y)) printf("-1\n");
124         else printf("%lld\n",lca(x,y));
125     }
126     return 0;
127 }
128 /*
129 10 24
130 4 7 19038
131 7 10 7375
132 7 9 17853
133 9 8 6341
134 7 2 16976
135 10 3 2835
136 10 4 19285
137 9 4 29193
138 3 4 4852
139 3 8 16597
140 9 1 4138
141 9 7 21611
142 7 4 10586
143 10 4 7821
144 10 9 25636
145 3 9 28425
146 2 3 17229
147 4 8 11331
148 9 2 25053
149 6 4 929
150 8 3 1738
151 10 9 28542
152 1 2 28343
153 3 5 13215
154 9
155 7 5
156 2 4
157 10 2
158 5 10
159 7 10
160 4 3
161 10 1
162 10 4
163 8 4
164 
165 */
166 /*
167 13215
168 25053
169 25053
170 13215
171 21611
172 28425
173 25053
174 28542
175 16597
176 */

猜你喜欢

转载自www.cnblogs.com/kylara/p/9748937.html