货车运输 (truck.cpp/c/pas)
【问题描述】 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。
【数据说明】
对于30%的数据,0<𝑛<1,000,0<𝑚<10,000,0<𝑞<1,000;
对于60%的数据,0<𝑛<1,000,0<𝑚<50,000,0<𝑞<1,000;
对于100%的数据,0<𝑛<10,000,0<𝑚<50,000,0<𝑞<30,000,0≤z≤100,000。
这道题算是我当时学习LCA tarjan离线算法的初始题了 老师拿这道题虐当年的我真的好意思吗?
今天复习LCA算法写一写这道题的解题报告。
首先跑一道最大生成树 为什么要跑最大生成树我现在也忘记了啊对不起我又没说人话了
然后针对题目的询问,找寻两个点的树上距离【说是树上距离其实是两个数的树上距离的最小值,类似于网络流的容量
然后输出这两个的树上距离就好了
贴代码,我也不知道当年的我写出了什么神奇的代码,不过能AC就是了
1 //先跑一遍最大生成树,然后求两个点的树上距离 2 //或许会用到倍增? 3 #include <algorithm> 4 #include <iostream> 5 #include <fstream> 6 #include <cstdlib> 7 #include <cstring> 8 #include <cmath> 9 using namespace std; 10 ifstream fin("truck.in"); 11 ofstream fout("truck.out"); 12 struct qxx 13 { 14 int nw; 15 int nxt; 16 int pay; 17 }; 18 qxx tree[70005];//生成树 19 struct bin 20 { 21 int x; 22 int y; 23 int v;//从x到y点有一条边权为v的边 24 }; 25 bin tu[100005];//单向边 26 int head[10005]={0},pa[10005][20]={0}/*倍增*/,pa1[10005]={0}/*kru用*/; 27 int pa2[10050]={0}/*tar用*/,least[10005][20]={0}; 28 int Cs[10050]={0},top=0; 29 int dians=0,bians=0,hcs=0,bian=0; 30 int tw[20]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288}; 31 int zhan[10050]={0}; 32 bool bj[10005]={0};//被检查过的点即为true 33 int ask[30005][3]={0};//询问,从ask[i][0]到ask[i][1], 34 //在tarjan后ask[i][3]为最近公共祖先,ST后为答案 35 int find_K(int x);//查找x所在集合的祖先 36 int find_T(int x);//查找x所在集合的祖先 37 void heb_K(int x,int y);// 38 void heb_T(int x,int y);// 合并x和y集合 39 void add(int fr,int to,int spend);// 40 void kru();//克鲁斯卡尔 41 void DFS(int nw);// 42 void tarjan(int nw);//最近公共祖先 43 void beiz(int cs);// 44 void ST(int bh);// 45 bool px(bin A,bin B);// 46 int Cz(int bh,int nw,int b);// 47 int main(void) 48 { 49 fin>>dians>>bians; 50 memset(least,127/2,sizeof(least)); 51 int a=0,b=0,c=0; 52 for(int i=1;i<=bians;i++) 53 { 54 fin>>a>>b>>c; 55 tu[i].x=a; 56 tu[i].y=b; 57 tu[i].v=c; 58 } 59 sort(tu+1,tu+bians+1,px); 60 kru();//最大生成树 61 Cs[1]=1; 62 DFS(1);//默认1号节点为根 63 pa[1][0]=1; 64 beiz(1); 65 fin>>hcs; 66 for(int i=1;i<=hcs;i++) 67 { 68 fin>>ask[i][0]>>ask[i][1]; 69 } 70 tarjan(1); 71 for(int i=1;i<=hcs;i++) 72 { 73 if(ask[i][2]==0) 74 { 75 fout<<"-1\n"; 76 continue; 77 } 78 memset(zhan,0,sizeof(zhan)); 79 top=0; 80 ST(i); 81 fout<<ask[i][2]<<"\n"; 82 } 83 return 0; 84 } 85 86 bool px(bin A,bin B) 87 { 88 if(A.v>B.v)return 1; 89 return 0; 90 } 91 92 int find_K(int x) 93 { 94 if(pa1[x]==0) 95 { 96 pa1[x]=x; 97 return x; 98 } 99 if(pa1[x]==x)return x; 100 else pa1[x]=find_K(pa1[x]); 101 return pa1[x]; 102 } 103 104 int find_T(int x) 105 { 106 if(pa2[x]==0) 107 { 108 pa2[x]=x; 109 return x; 110 } 111 if(pa2[x]==x)return x; 112 int a=x; 113 while(pa2[a]!=a)a=pa2[a]; 114 return a; 115 } 116 117 void add(int fr,int to,int spend) 118 { 119 tree[++bian].nw=to; 120 tree[bian].nxt=head[fr]; 121 tree[bian].pay=spend; 122 head[fr]=bian; 123 tree[++bian].nw=fr; 124 tree[bian].nxt=head[to]; 125 tree[bian].pay=spend; 126 return; 127 } 128 129 void heb_K(int x,int y) 130 { 131 int Px=0,Py=0; 132 Px=find_K(x); 133 Py=find_K(y); 134 pa1[Py]=Px; 135 return; 136 } 137 138 void heb_T(int x,int y) 139 { 140 int Px=0,Py=0; 141 Px=find_T(x); 142 Py=find_T(y); 143 pa2[Py]=Px; 144 return; 145 } 146 147 void DFS(int nw) 148 { 149 int child=0; 150 for(int i=head[nw];i>0;i=tree[i].nxt) 151 { 152 child=tree[i].nw; 153 if(pa[nw][0]==child)continue; 154 pa[child][0]=nw; 155 Cs[child]=Cs[nw]+1; 156 least[child][0]=tree[i].pay; 157 DFS(child); 158 } 159 return; 160 } 161 162 void beiz(int cs) 163 { 164 if(cs>=18)return; 165 for(int i=1;i<=dians;i++) 166 { 167 pa[i][cs]=pa[pa[i][cs-1]][cs-1]; 168 least[i][cs]=min(least[pa[i][cs-1]][cs-1],least[i][cs-1]); 169 } 170 beiz(cs+1); 171 return; 172 } 173 174 void kru() 175 { 176 int Px=0,Py=0,xq=0; 177 for(int i=1;i<=bians;i++) 178 { 179 if(xq==dians-1)break; 180 Px=find_K(tu[i].x); 181 Py=find_K(tu[i].y); 182 if(Px==Py)continue; 183 xq++; 184 heb_K(tu[i].x,tu[i].y); 185 add(tu[i].x,tu[i].y,tu[i].v); 186 add(tu[i].y,tu[i].x,tu[i].v); 187 } 188 return; 189 } 190 191 void tarjan(int nw) 192 { 193 pa2[nw]=nw; 194 int child=0; 195 for(int i=head[nw];i>0;i=tree[i].nxt) 196 { 197 child=tree[i].nw; 198 if(child==pa[nw][0])continue; 199 tarjan(child); 200 heb_T(nw,child); 201 } 202 bj[nw]=true; 203 for(int i=1;i<=hcs;i++) 204 { 205 if(ask[i][0]==nw) 206 { 207 if(bj[ask[i][1]])ask[i][2]=find_T(ask[i][1]); 208 } 209 if(ask[i][1]==nw) 210 { 211 if(bj[ask[i][0]])ask[i][2]=find_T(ask[i][0]); 212 } 213 } 214 return; 215 } 216 217 void ST(int bh) 218 { 219 220 int S1=abs(Cs[ask[bh][0]]-Cs[ask[bh][2]]); 221 int S2=abs(Cs[ask[bh][1]]-Cs[ask[bh][2]]); 222 223 double K1=log((double)S1)/log((double)2); 224 double K2=log((double)S2)/log((double)2); 225 226 int k1=(int)K1; 227 int k2=(int)K2; 228 229 int As1=least[ask[bh][0]][k1]; 230 int As2=least[Cz(bh,ask[bh][0],tw[k1])][k1]; 231 int As3=0; 232 233 if(As2<As1)As1=As2; 234 if(ask[bh][0]==ask[bh][2])As1=0x7fffffff; 235 236 memset(zhan,0,sizeof(zhan)); 237 top=0; 238 As2=least[ask[bh][1]][k2]; 239 As3=least[Cz(bh,ask[bh][1],tw[k2])][k2]; 240 241 if(As3<As2)As2=As3; 242 if(ask[bh][1]==ask[bh][2])As2=0x7fffffff; 243 244 ask[bh][2]=min(As1,As2); 245 } 246 247 int Cz(int bh,int nw,int b) 248 { 249 zhan[++top]=nw; 250 if(nw==ask[bh][2]) 251 { 252 return zhan[top-b]; 253 } 254 return Cz(bh,pa[nw][0],b); 255 }