Gym 101889I Imperial roads 倍增求次小生成树

题目链接:https://odzkskevi.qnssl.com/fa6682426fb11e87a5ab9246f22a461d?v=1538477779

 

题意:

       给你n点m边的图,给你q个询问,每个询问都有一个a和b,要你输出保留点a和点b这条边后的最小生成树的权值。

 

做法:

       用倍增的方法保存一个maxx[i][j]表示点i向上走(1<

 


#include
using namespace std;
const int maxn=400005;
const int maxm=400005;
int dist[maxn],fa[maxn][30],n,m,q,head[maxn],now,vis[maxn];
int dep[maxn],ff[maxn],maxx[maxn][30],qu[maxn],qv[maxn],qw[maxn];
struct edge{
    int u,v,val;
    bool operator < (const edge &a) const {
        if(u!=a.u) return u mp;
bool cmp(edge a,edge b){
    return a.val=0;i--)
        if(dep[x]-(1<=dep[y]){
            ans=max(ans,maxx[x][i]);
            x=fa[x][i];
        }

    if(x==y) return ans;

    for(int i=pos;i>=0;i--)
        if(fa[x][i]!=fa[y][i]&&fa[x][i]!=-1){
            ans=max(ans,maxx[x][i]);
            ans=max(ans,maxx[y][i]);
            x=fa[x][i],y=fa[y][i];
        }
    ans=max(ans,maxx[x][0]);
    ans=max(ans,maxx[y][0]);
    return ans;
}
void init(){
    memset(fa,-1,sizeof(fa));
}
int main(){
    int x,y,z;
    mp.clear();
    init();
    scanf("%d%d",&n,&m);
    for(int i=0;i<=n;i++)
        ff[i]=i,head[i]=-1;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&ed[i].u,&ed[i].v,&ed[i].val);
    }
    scanf("%d",&q);
    for(int i=1;i<=q;i++){
        scanf("%d%d",&qu[i],&qv[i]);
        mp[edge{qu[i],qv[i],0}]=i;
        mp[edge{qv[i],qu[i],0}]=i;
    }
    for(int i=1;i<=m;i++){
        int t=mp[edge{ed[i].u,ed[i].v,0}];
        if(t!=0) qw[t]=ed[i].val;
    }
    sort(ed+1,ed+1+m,cmp);
    int sum=0,num=0;
    for(int i=1;i<=m&&num

 

你可能感兴趣的:(图论)