【NOIP2013】货车运输

本题在洛谷上的链接:https://www.luogu.org/problemnew/show/P1967


好坑啊!算了,还是怪我LCA写的不熟,沙茶一般把j<maxb写成(1<<j)<maxb。。。

首先,我们可以生成一下最大生成树,保证每个点都连通的情况下,每条路的限重尽量大。但是注意点并不一定都连通,因此我们需要建立多棵最大生成树。然后我们的任务就是查询两点间路径上的最小边权,暴力的话复杂度难以接受,这是我们就可以使用一种较好的方法——倍增。说白了,就是在求LCA的同时维护路径上的最小边权。初始化时,mine[i][0]=w[i][fan[i][0]];然后有mine[i][j]=min(mine[i][j-1],mine[fan[i][j-1]][j-1])。再就是建树的过程容易出错,应该注意。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 inline int min(int a,int b) {return a<b?a:b;}
 7 inline void swap(int& a,int& b) {int t=a;a=b;b=t;}
 8 inline int get_num() {
 9     int num;char c;
10     while((c=getchar())=='\n'||c==' '||c=='\r');
11     num=c-'0';
12     while(isdigit(c=getchar())) num=num*10+c-'0';
13     return num;
14 }
15 void put_num(int i) {
16     if(i<0) putchar('-'),i=-i;
17     if(i>9) put_num(i/10);
18     putchar(i%10+'0');
19 }
20 const int maxn=1e4+5,maxm=5e4+5,maxb=15,inf=0x3f3f3f3f;
21 struct Edge {
22     int u,v,w;
23     bool operator < (const Edge& rhs) const {
24         return w>rhs.w;
25     }
26 } edge[maxm];
27 int fa[maxn],d[maxn],fan[maxn][maxb],mine[maxn][maxb];
28 int f(int i) {
29     if(i==fa[i]) return i;
30     else return fa[i]=f(fa[i]);
31 }
32 int dfs(int v) {
33     if(d[v]) return d[v];
34     if(f(v)) return d[v]=dfs(fan[v][0])+1;
35     else return 1;
36 }
37 int query(int x,int y) {
38     if(d[x]<d[y]) swap(x,y);
39     int i,j,mmin=inf;
40     for(i=0;(1<<i)<=d[x];++i);
41     --i;
42     for(j=i;j>=0;--j)
43         if(d[x]-(1<<j)>=d[y])
44             mmin=min(mmin,mine[x][j]),x=fan[x][j];
45     if(x==y) return mmin;
46     for(j=i;j>=0;--j)
47         if(fan[x][j]!=fan[y][j]) {
48             mmin=min(mmin,min(mine[x][j],mine[y][j]));
49             x=fan[x][j],y=fan[y][j];
50         }
51     return min(mmin,min(mine[x][0],mine[y][0]));
52 }
53 int main() {
54     int n,m,x,y,z,cnt=0;
55     n=get_num();m=get_num();
56     for(int i=1;i<=m;++i) {
57         x=get_num();y=get_num();z=get_num();
58         edge[i].u=x,edge[i].v=y,edge[i].w=z;
59     }
60     sort(edge+1,edge+m+1);
61     for(int i=1;i<=n;++i) fa[i]=i;
62     memset(mine,inf,sizeof(mine));
63     for(int i=1;i<=m&&cnt<n-1;++i) {
64         int u=f(edge[i].u),v=f(edge[i].v),w=edge[i].w;
65         if(u!=v) fa[v]=u,fan[v][0]=u,mine[v][0]=w,++cnt;
66     }
67     for(int i=1;i<=n;++i) {
68         int root=f(i);
69         d[root]=1;
70         if(!d[i]) dfs(i);
71     }
72     for(int j=1;j<maxb;++j)
73         for(int i=1;i<=n;++i) {
74             fan[i][j]=fan[fan[i][j-1]][j-1];
75             mine[i][j]=min(mine[i][j-1],mine[fan[i][j-1]][j-1]);
76         }
77     int q=get_num(),first=1;
78     for(int i=1;i<=q;++i) {
79         x=get_num();y=get_num();
80         if(first) first=0;
81         else putchar('\n');
82         if(f(x)!=f(y)) put_num(-1);
83         else put_num(query(x,y));
84     }
85     return 0;
86 }
AC代码

猜你喜欢

转载自www.cnblogs.com/Mr94Kevin/p/9745789.html
今日推荐