生活随笔
收集整理的這篇文章主要介紹了
[NOIp 2013]货车运输
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Description
A 國(guó)有 n 座城市,編號(hào)從 1 到 n,城市之間有 m 條雙向道路。每一條道路對(duì)車輛都有重量限制,簡(jiǎn)稱限重。現(xiàn)在有 q 輛貨車在運(yùn)輸貨物, 司機(jī)們想知道每輛車在不超過車輛限重的情況下,最多能運(yùn)多重的貨物。
Input
輸入文件名為 truck.in。
輸入文件第一行有兩個(gè)用一個(gè)空格隔開的整數(shù) n,m,表示 A 國(guó)有 n 座城市和 m 條道
路。 接下來 m 行每行 3 個(gè)整數(shù) x、 y、 z,每?jī)蓚€(gè)整數(shù)之間用一個(gè)空格隔開,表示從 x 號(hào)城市到 y 號(hào)城市有一條限重為 z 的道路。注意: x 不等于 y,兩座城市之間可能有多條道路 。
接下來一行有一個(gè)整數(shù) q,表示有 q 輛貨車需要運(yùn)貨。
接下來 q 行,每行兩個(gè)整數(shù) x、y,之間用一個(gè)空格隔開,表示一輛貨車需要從 x 城市運(yùn)輸貨物到 y 城市,注意: x 不等于 y 。
Output
輸出文件名為 truck.out。
輸出共有 q 行,每行一個(gè)整數(shù),表示對(duì)于每一輛貨車,它的最大載重是多少。如果貨
車不能到達(dá)目的地,輸出-1。
Sample Input
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3 Sample Output
3
-1
3 Hint
對(duì)于 30%的數(shù)據(jù),0 < n < 1,000,0 < m < 10,000,0 < q< 1,000;
對(duì)于 60%的數(shù)據(jù),0 < n < 1,000,0 < m < 50,000,0 < q< 1,000;
對(duì)于 100%的數(shù)據(jù),0 < n < 10,000,0 < m < 50,000,0 < q< 30,000,0 ≤ z ≤ 100,000。
題解
$Kruskal$+$LCA$+并查集
?? ?建最大生成森林(以保證聯(lián)通性的情況下最大化瓶頸路徑)。
?? ?并查集判斷是否聯(lián)通。
?? ?若聯(lián)通,$LCA$出路徑上的最短邊。
1 #include<map>
2 #include<ctime>
3 #include<cmath>
4 #include<queue>
5 #include<stack>
6 #include<cstdio>
7 #include<
string>
8 #include<vector>
9 #include<cstring>
10 #include<cstdlib>
11 #include<iostream>
12 #include<algorithm>
13 #define LL long long
14 #define RE register
15 #define IL inline
16 using namespace std;
17 const int N=
10000;
18 const int M=
50000;
19
20 IL
int Min(
const int &a,
const int &b) {
return a<b ?
a:b;}
21
22 int n,m,q,lim,x,y;
23 struct tt
24 {
25 int from,to,cost;
26 }lin[M+
5];
27 IL
bool comp(
const tt &a,
const tt &b) {
return a.cost>
b.cost;}
28
29 int set[N+
5];
30 IL
int Find(
int r) {
return set[r] ?
set[r]=Find(
set[r]):r;}
31 IL
void Kruskal();
32
33 struct ss
34 {
35 int to,next,cost;
36 }edge[N*
2+
5];
37 int path[N+
5],top;
38 IL
void Add(
int u,
int v,
int c);
39
40 bool vis[N+
5];
41 int fa[N+
5][
15],minn[N+
5][
15],dep[N+
5];
42 void Dfs(
int r,
int depth);
43 IL
void RMQ();
44
45 IL
int LCA(
int x,
int y);
46
47 int main()
48 {
49 scanf(
"%d%d",&n,&m);lim=
log2(n);
50 for (RE
int i=
1;i<=m;i++) scanf(
"%d%d%d",&lin[i].
from,&lin[i].to,&
lin[i].cost);
51 Kruskal();
52 for (RE
int i=
1;i<=n;i++)
if (!vis[i]) Dfs(i,
1);
53 RMQ();
54 scanf(
"%d",&
q);
55 while (q--
)
56 {
57 scanf(
"%d%d",&x,&
y);
58 int a=
Find(x);
59 int b=
Find(y);
60 if (a!=b) printf(
"-1\n");
61 else printf(
"%d\n",LCA(x,y));
62 }
63 return 0;
64 }
65
66 IL
void Kruskal()
67 {
68 sort(lin+
1,lin+m+
1,comp);
69 int cnt=
0;
70 for (RE
int i=
1;i<=m;i++
)
71 {
72 int q=Find(lin[i].
from);
73 int p=
Find(lin[i].to);
74 if (p!=
q)
75 {
76 set[p]=
q;
77 cnt++
;
78 Add(lin[i].
from,lin[i].to,lin[i].cost);
79 Add(lin[i].to,lin[i].
from,lin[i].cost);
80 if (cnt==n-
1)
break;
81 }
82 }
83 }
84 IL
void Add(
int u,
int v,
int c)
85 {
86 edge[++top].to=
v;
87 edge[top].next=
path[u];
88 edge[top].cost=
c;
89 path[u]=
top;
90 }
91 void Dfs(
int r,
int depth)
92 {
93 vis[r]=
1;
94 dep[r]=
depth;
95 for (RE
int i=path[r];i;i=edge[i].next)
if (!
vis[edge[i].to])
96 {
97 fa[edge[i].to][
0]=
r;
98 minn[edge[i].to][
0]=
edge[i].cost;
99 Dfs(edge[i].to,depth+
1);
100 }
101 }
102 IL
void RMQ()
103 {
104 for (RE
int t=
1;t<=lim;t++
)
105 for (RE
int i=
1;i<=n;i++
)
106 {
107 fa[i][t]=fa[fa[i][t-
1]][t-
1];
108 minn[i][t]=Min(minn[i][t-
1],minn[fa[i][t-
1]][t-
1]);
109 }
110 }
111 IL
int LCA(
int x,
int y)
112 {
113 int ans=
2e9;
114 if (dep[x]<
dep[y]) swap(x,y);
115 for (RE
int i=lim;i>=
0;i--)
if (dep[x]-(
1<<i)>=
dep[y])
116 {
117 ans=
Min(ans,minn[x][i]);
118 x=
fa[x][i];
119 }
120 if (x!=
y)
121 {
122 for (RE
int i=lim;i>=
0;i--)
if (fa[x][i]!=
fa[y][i])
123 {
124 ans=
Min(ans,minn[x][i]);
125 ans=
Min(ans,minn[y][i]);
126 x=
fa[x][i];
127 y=
fa[y][i];
128 }
129 ans=Min(ans,minn[x][
0]);
130 ans=Min(ans,minn[y][
0]);
131 x=fa[x][
0];
132 y=fa[y][
0];
133 }
134 return ans;
135 }
?
轉(zhuǎn)載于:https://www.cnblogs.com/NaVi-Awson/p/7366014.html
總結(jié)
以上是生活随笔為你收集整理的[NOIp 2013]货车运输的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。