货车运输(NOIP2013)

题目链接:货车运输
这道题其实思路很显然,就是最大生成树加倍增。
我们来顺着代码讲一遍。
我们先读入n和m
然后把所有边的权值设置为0
读入时,重复的边只取最大(很显然)
然后kruscal进行最大生成树,用G和H两个vector分别去保存边和权值
然后倍增即可。
具体看代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
struct edge{//边
    int u,v,w;
};
int n,m;
int p[10005];//父节点(用于最大生成树)
edge e[50005];
int f[10005][21],deep[10005];//f表示节点u的k级祖先,deep是深度
int g[10005][21];//表示节点u到u的k级祖先上最小权值
int vis[10005]; //用于bfs
vector<int> G[10005],H[10005];//保存树的边和权值
//int fa[10005];
int ques;
int find(int xx){
    return xx==p[xx]?xx:p[xx]=find(p[xx]);
}
int cmp(edge a,edge b){
    return a.w>b.w;
}
void kruscal(){
    sort(e,e+m,cmp);
    for(int i=1;i<=n;i++){
        p[i]=i;
    }
    for(int i=0;i<m;i++){
        int xx=find(e[i].u),yy=find(e[i].v);
        if(xx!=yy){
            p[xx]=yy;
            G[e[i].u].push_back(e[i].v);
            G[e[i].v].push_back(e[i].u);
            H[e[i].u].push_back(e[i].w);
            H[e[i].v].push_back(e[i].w);

        }
    }
}
void bfs(){
    memset(g,0x3f,sizeof(g));
    memset(vis,0,sizeof(vis));
    memset(f,-1,sizeof(f));
    queue<int> q;
    int cur=1;
    deep[cur]=1;
    q.push(cur);
    vis[cur]=1;
//  f[cur][0]=-1;
//  fa[cur]=-1;
    while(!q.empty()){
        cur=q.front();
        q.pop(); 
        int len=G[cur].size();
        for(int i=0;i<len;i++){
            if(vis[G[cur][i]]==0){
                q.push(G[cur][i]);
                vis[G[cur][i]]=1;
                deep[G[cur][i]]=deep[cur]+1;
                f[G[cur][i]][0]=cur; 
                g[G[cur][i]][0]=H[cur][i];
            }
        }
    }
}
void init(){
    for(int k=0;k<20;k++){
        for(int j=1;j<=n;j++){
            if(f[j][k]!=-1){
                f[j][k+1]=f[f[j][k]][k];
                g[j][k+1]=min(g[j][k],g[f[j][k]][k]);
            }
        }
    }
}
int ans;
int jump(int u,int step){
    for(int k=0;k<21;k++){
        if(step&(1<<k)){
            ans=min(ans,g[u][k]);
            u=f[u][k];

        }
    }
    return u;
}
void lca(int u,int v){
    ans=0x3f3f3f3f;
    if(deep[u]<deep[v]){
        swap(u,v);
    }
    u=jump(u,deep[u]-deep[v]);
    for(int k=20;k>=0;k--){
        if(f[u][k]!=f[v][k]){
            ans=min(min(ans,g[u][k]),g[v][k]);
            u=f[u][k];
            v=f[v][k];
        }
    }
    ans=u==v?ans:min(min(ans,g[u][0]),g[v][0]);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        e[i].w=0;
    }
    for(int i=0;i<m;i++){
        int ww;
        scanf("%d%d%d",&e[i].u,&e[i].v,&ww);
        e[i].w=max(e[i].w,ww);
    }
    kruscal();
    bfs();
    init();
    scanf("%d",&ques);
    while(ques--){
        int u,v;
        scanf("%d%d",&u,&v);
        if(u>n||v>n){
            printf("-1\n");
            continue;
        }
        if(find(u)!=find(v)){
            printf("-1\n");
            continue;
        }else{
            lca(u,v);
            if(ans<0x3f3f3f3f){
                printf("%d\n",ans);
            }else{
                printf("-1\n");
            }
        }
    }
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/cggwz/article/details/81071152