「NOIP2013」「LuoguP1967」貨車運輸(最大生成樹 倍增 LCA 「LuoguP4180」 【模板】嚴格次小生成樹[BJWC2010](倍增 LCA Kruscal
題目描述
AA國有nn座城市,編號從 11到nn,城市之間有 mm 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 qq 輛貨車在運輸貨物, 司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。
輸入輸出格式
輸入格式:
第一行有兩個用一個空格隔開的整數n,mn,m,表示 AA 國有nn 座城市和 mm 條道路。
接下來 mm行每行33個整數 x, y, zx,y,z,每兩個整數之間用一個空格隔開,表示從 xx號城市到yy號城市有一條限重為 zz 的道路。注意: xx 不等於 yy,兩座城市之間可能有多條道路 。
接下來一行有一個整數 q,表示有 q 輛貨車需要運貨。
接下來 q 行,每行兩個整數 x、y,之間用一個空格隔開,表示一輛貨車需要從 x 城市運輸貨物到 y 城市,注意:x 不等於 y 。
輸出格式:
共有 qq 行,每行一個整數,表示對於每一輛貨車,它的最大載重是多少。如果貨車不能到達目的地,輸出-1−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\%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\%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\%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,0≤z≤100,000。
題解
跑個最大生成樹,然後對於每次詢問在最大生成樹上走樹上路徑,就能保證運的最重。
所以對於每次詢問,如果兩點在一個聯通塊上,輸出樹上路徑的最小邊權值,否則輸出-1就行了。
實現過程很像「LuoguP4180」 【模板】嚴格次小生成樹[BJWC2010](倍增 LCA Kruscal,但是要好碼一丟丟。
1 /* 2 qwerta 3 P1967 貨車運輸 Accepted 4 100 5 程式碼 C++,1.84KB 6 提交時間 2018-11-02 22:17:58 7 耗時/記憶體 453ms, 2548KB 8 */ 9 #include<algorithm> 10 #include<iostream> 11 #include<cstdio> 12 #include<cmath> 13 using namespace std; 14 const int MAXN=10000+3,MAXM=50000+3; 15 struct emm{ 16 int x,y,l; 17 }b[MAXM]; 18 bool cmpb(emm qaq,emm qwq){ 19 return qaq.l>qwq.l; 20 } 21 int fa[MAXN]; 22 int fifa(int x) 23 { 24 if(fa[x]==x)return x; 25 return fa[x]=fifa(fa[x]); 26 } 27 struct ahh{ 28 int e,f,l; 29 }a[2*MAXN]; 30 int h[MAXN]; 31 int tot=0; 32 void con(int x,int y,int l) 33 { 34 a[++tot].f=h[x]; 35 h[x]=tot; 36 a[tot].e=y; 37 a[tot].l=l; 38 a[++tot].f=h[y]; 39 h[y]=tot; 40 a[tot].e=x; 41 a[tot].l=l; 42 return; 43 } 44 int d[MAXN]; 45 int f[MAXN][13]; 46 int mi[MAXN][13]; 47 void dfs(int x) 48 { 49 for(int i=h[x];i;i=a[i].f) 50 if(!d[a[i].e]) 51 { 52 d[a[i].e]=d[x]+1; 53 f[a[i].e][0]=x; 54 mi[a[i].e][0]=a[i].l; 55 dfs(a[i].e); 56 } 57 return; 58 } 59 bool sf[MAXN]; 60 int main() 61 { 62 //freopen("a.in","r",stdin); 63 int n,m; 64 scanf("%d%d",&n,&m); 65 for(int i=1;i<=m;++i) 66 { 67 scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].l); 68 } 69 sort(b+1,b+m+1,cmpb); 70 for(int i=1;i<=n;++i) 71 fa[i]=i; 72 int k=n-1,i=0; 73 while(k&&i<=m) 74 { 75 i++; 76 int u=fifa(b[i].x),v=fifa(b[i].y); 77 if(u!=v) 78 { 79 //cout<<i<<" "<<b[i].x<<" "<<b[i].y<<" "<<b[i].l<<endl; 80 fa[u]=v; 81 con(b[i].x,b[i].y,b[i].l); 82 k--; 83 } 84 } 85 for(int s=1;s<=n;++s) 86 if(!sf[fifa(s)]) 87 { 88 sf[fifa(s)]=1; 89 d[s]=1; 90 dfs(s); 91 } 92 for(int j=1;j<=10;++j) 93 for(int i=1;i<=n;++i) 94 { 95 f[i][j]=f[f[i][j-1]][j-1]; 96 mi[i][j]=min(mi[i][j-1],mi[f[i][j-1]][j-1]); 97 } 98 int q; 99 scanf("%d",&q); 100 while(q--) 101 { 102 int u,v; 103 scanf("%d%d",&u,&v); 104 if(fifa(u)!=fifa(v)){printf("-1\n");continue;} 105 if(d[u]<d[v])swap(u,v); 106 int ans=1e6+2333; 107 for(int j=10;j>=0;--j) 108 if(d[u]-d[v]>=(1<<j)) 109 { 110 ans=min(ans,mi[u][j]); 111 u=f[u][j]; 112 } 113 if(u==v){printf("%d\n",ans);continue;} 114 for(int j=10;j>=0;--j) 115 if(f[u][j]!=f[v][j]) 116 { 117 ans=min(ans,mi[u][j]); 118 u=f[u][j]; 119 ans=min(ans,mi[v][j]); 120 v=f[v][j]; 121 } 122 ans=min(ans,mi[u][0]); 123 ans=min(ans,mi[v][0]); 124 printf("%d\n",ans); 125 } 126 return 0; 127 }