A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入格式:
输入文件名为 truck.in。
输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道
路。 接下来 m 行每行 3 个整数 x、 y、 z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意: x 不等于 y,两座城市之间可能有多条道路 。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y 。
输出格式:
输出文件名为 truck.out。
输出共有 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,000;
对于 60%的数据,0 < 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,000。
和这道题熬战总计7.5小时后终于调试出来了!!
思路我就不多说了,跑一边最大树然后倍增求LCA不断取最小值就好
我在这里说一下这道题容易犯的错误
1.在读入第一个图的时候必须用有向边储存,但是跑最大生成树产生的图必须用无向图储存
2.在选择源点的时候可以从1->n进行dfs,但是必须要开一个vis数组,单纯一个deep数组是不可以的
3.在从低处点往高处点跳的时候判断条件一定是deep[s[x][i]]>=deep[y],必须是>=!!!
4.在取最小值得时候一定是在更新变量之前取!!
5.注意各种变量的初始化!
因为调试时间比较长,所以代码可以比较长,但没什么高大上的语句,写的还算简单
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<algorithm>
6 using namespace std;
7 const int MAXN=50001;
8 int n,m;
9 int x,y,z;
10 int vis[MAXN];
11 struct node
12 {
13 int u,v,w,next;
14 }edge[MAXN],a[MAXN];
15 int num=1;
16 int head[MAXN];
17 int f[MAXN];
18 int anum=1;
19 int ahead[MAXN];
20 int deep[MAXN];
21 int s[MAXN][20];
22 int take[MAXN][20];
23 void edge_add(int x,int y,int z)
24 {
25 edge[num].u=x;
26 edge[num].v=y;
27 edge[num].w=z;
28 edge[num].next=head[x];
29 head[x]=num++;
30 }
31 void a_add(int i)
32 {
33 a[anum].u=edge[i].u;
34 a[anum].v=edge[i].v;
35 a[anum].w=edge[i].w;
36 a[anum].next=ahead[a[anum].u];
37 ahead[a[anum].u]=anum++;
38 a[anum].u=edge[i].v;
39 a[anum].v=edge[i].u;
40 a[anum].w=edge[i].w;
41 a[anum].next=ahead[a[anum].u];
42 ahead[a[anum].u]=anum++;
43 }
44 int comp(const node & a ,const node & b)
45 {return a.w>b.w;}
46
47 int find(int x)
48 {
49 if(f[x]!=x)
50 f[x]=find(f[x]);
51 return f[x];
52 }
53 void unionn(int x,int y)
54 {
55 int fx=find(x);
56 int fy=find(y);
57 f[fx]=fy;
58 }
59 void Biggest_Kruskal()
60 {
61 sort(edge+1,edge+num+1,comp);
62 int k=0;
63 for(int i=1;i<=num;i++)
64 {
65 int uu=edge[i].u;
66 int vv=edge[i].v;
67 if(find(uu)!=find(vv))
68 {
69 a_add(i);
70 unionn(uu,vv);
71 k++;
72 }
73 if(k==n-1)break;
74 }
75 //for(int i=1;i<=anum;i++)
76 // cout<<a[i].u<<" "<<a[i].v<<" "<<a[i].w<<" "<<a[i].next<<endl;
77 }
78 void Build_Tree(int p)
79 {
80 vis[p]=1;
81 for(int i=ahead[p];i!=-1;i=a[i].next)
82 {
83 int will=a[i].v;
84 if(vis[will])continue;
85 vis[will]=1;
86
87 deep[will]=deep[p]+1;
88 s[will][0]=p;
89 take[will][0]=a[i].w;
90 Build_Tree(will);
91 }
92 }
93 void Initialize_Step()
94 {
95 for(int i=1;i<=18;i++)
96 {
97 for(int j=1;j<=n;j++)
98 {
99 s[j][i]=s[s[j][i-1]][i-1];
100 take[j][i]=min(take[j][i-1],take[s[j][i-1]][i-1]);
101 }
102 }
103 }
104 int LCA(int x,int y)
105 {
106 int ans=0x7ffffff;
107 if(deep[x]<deep[y])
108 swap(x,y);
109 for(int i=18;i>=0;i--)
110 {
111 if(s[x][i]!=0)
112 if(deep[s[x][i]]>=deep[y])
113 {
114 ans=min(ans,take[x][i]);
115 x=s[x][i];
116 }
117 }
118 if(x==y)
119 return ans;
120 for(int i=18;i>=0;i--)
121 {
122 if(s[x][i]!=s[y][i])
123 {
124 ans=min(ans,take[x][i]);
125 ans=min(ans,take[y][i]);
126 x=s[x][i];
127 y=s[y][i];
128 }
129 }
130 ans=min(ans,take[x][0]);
131 ans=min(ans,take[y][0]);
132 return ans;
133 }
134 int main()
135 {
136 // memset(take,0xf,sizeof(take));
137 scanf("%d%d",&n,&m);
138
139 for(int i=1;i<=n;i++)
140 {head[i]=-1;f[i]=i;ahead[i]=-1;}
141
142 for(int i=1;i<=m;i++)
143 {
144 scanf("%d%d%d",&x,&y,&z);
145 edge_add(x,y,z);
146 //edge_add(y,x,z);
147 }
148 Biggest_Kruskal();
149 //deep[1]=1;
150 for(int i=1;i<=n;i++)
151 {
152 if(vis[i]==0)
153 Build_Tree(i);
154 }
155
156 Initialize_Step();
157 int q;
158 scanf("%d",&q);
159 for(int i=1;i<=q;i++)
160 {
161 int x,y;
162 scanf("%d%d",&x,&y);
163 if(find(x)!=find(y))
164 {
165 printf("-1\n");
166 continue;
167 }
168 printf("%d\n",LCA(x,y));
169 }
170 return 0;
171 }