2013年NOIP全国联赛提高组
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。
接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
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。
题解:
树上倍增LCA...
代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<vector> 4 #include<algorithm> 5 #define maxn 10010 6 7 using namespace std; 8 9 vector<int> p[maxn],c[maxn]; 10 11 struct node 12 { 13 int l,r,v; 14 }s[50010]; 15 16 struct ss 17 { 18 int p; 19 int c; 20 } f[maxn][50]; 21 22 bool cmp(node a,node b) 23 { 24 return a.v>b.v; 25 } 26 int deep[maxn],n,m,fa[maxn],kg[maxn]; 27 28 void getree(int k,int d) 29 { 30 deep[k]=d; 31 kg[k]=1; 32 for (int i=1;(1<<i)<=deep[k];i++) 33 { 34 f[k][i].p=f[f[k][i-1].p][i-1].p; 35 f[k][i].c=min(f[k][i-1].c,f[f[k][i-1].p][i-1].c); 36 } 37 for (int i=0;i<p[k].size();i++) 38 if (!deep[p[k][i]]) 39 { 40 f[p[k][i]][0].p=k; 41 f[p[k][i]][0].c=c[k][i]; 42 getree(p[k][i],d+1); 43 } 44 } 45 int lca(int a,int b) 46 { 47 if (deep[a]<deep[b]) swap(a,b); 48 int t=deep[a]-deep[b]; 49 int ans=0x7fffffff; 50 for (int i=0;i<=20;i++) 51 if ((1<<i)&t) { 52 ans=min(f[a][i].c,ans); 53 a=f[a][i].p; 54 } 55 for (int i=20;i>=0;i--) 56 if (f[a][i].p!=f[b][i].p) 57 { 58 ans=min(f[b][i].c,ans); 59 ans=min(f[a][i].c,ans); 60 a=f[a][i].p; 61 b=f[b][i].p; 62 } 63 if (a==b) return ans; 64 else return min(f[a][0].c,min(f[b][0].c,ans)); 65 } 66 67 int find(int x) 68 { 69 if (fa[x]==x) return x; 70 fa[x]=find(fa[x]); 71 return fa[x]; 72 } 73 74 void init() 75 { 76 scanf("%d%d",&n,&m); 77 for (int i=0;i<m;i++) 78 scanf("%d%d%d",&s[i].l,&s[i].r,&s[i].v); 79 sort(s+0,s+m,cmp); 80 for (int i=0;i<=n;i++) 81 fa[i]=i; 82 } 83 int main() 84 { 85 init(); 86 for (int i=0;i<m;i++) 87 { 88 int pp=find(s[i].l); 89 int qq=find(s[i].r); 90 if (pp!=qq) 91 { 92 fa[pp]=qq; 93 p[s[i].l].push_back(s[i].r); 94 c[s[i].l].push_back(s[i].v); 95 p[s[i].r].push_back(s[i].l); 96 c[s[i].r].push_back(s[i].v); 97 } 98 } 99 for (int i=1;i<=n;i++) 100 if (!kg[i]) getree(i,1); 101 scanf("%d",&m); 102 for (int i=0;i<m;i++) 103 { 104 int x,y; 105 scanf("%d%d",&x,&y); 106 if (find(x)!=find(y)) printf("-1\n"); 107 else printf("%d\n",lca(x,y)); 108 } 109 return 0; 110 }
原文:http://www.cnblogs.com/grhyxzc/p/5132717.html