BZOJ P2654 tree [minimum spanning tree] [two-point answer]

Topic index: https://www.lydsy.com/JudgeOnline/problem.php?id=2654

2654: tree

Time Limit: 30 Sec   Memory Limit: 512 MB
Submit: 2768   Solved: 1136
[ Submit ][ Status ][ Discuss ]

Description

gives you an undirected weighted connected graph where each edge is black or white. Let you find a minimum weight spanning tree with exactly need white edges.
The problem is guaranteed to be solved.

Input

The first line V, E, and need respectively indicate the number of points, the number of sides and the number of white sides required.
Next E line, each line s, t, c, col represents the endpoint of this side (points start from 0), edge weight, color (0 white 1 black).

Output

One line represents the sum of edge weights of the desired spanning tree.
V<=50000, E<=100000, all data edge weights are positive integers in [1,100].

Sample Input

2 2 1
0 1 1 1
0 1 2 0

Sample Output

2

HINT

The original data is wrong, it has been updated by  liutian , but not retested---2016.6.24

Source


Topic Analysis:

       Find the weight of the minimum spanning tree that satisfies the meaning of the question -> first meet the requirements -> the selected minimum spanning tree has a need white edge -> but the selected minimum spanning tree does not necessarily have a need white edge -> For each time Kruskal-> we can get the number of white edges in the current minimum spanning tree Cnt-> if Cnt>need->the number of white edges is more than needed->the weight of the white edges is too small->make each A value is added to each white edge -> it is possible to reduce the Cnt counted by Kruskal the next time -> if the number of Cnt<need -> the number of white edges is less than required -> the weight of the white edge is too large -> Subtract a value from each white edge -> Make it possible to increase the Cnt counted by Kruskal next time -> How do we modify the weight of the white edge -> How much to modify the weight of the white edge -> Get the solution -> Dichotomous answer + spanning tree.

code show as below:

        

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define DB double
#define SG string
#define LL long long
#define Fp(A,B,C,D) for(A=B;A<=C;A+=D)
#define Fm(A,B,C,D) for(A=B;A>=C;A-=D)
#define Clear(A) memset(A,0,sizeof(A))
using namespace std;
const LL Max=1e5+5;
const LL Mod=1e9+7;
const LL Inf=1e18;
struct Node{
    LL C,X,Y,V;
    void Get(LL A,LL B,LL P,LL Q){
        C=A;X=B;Y=P;V=Q;
    }
}G[Max<<1];
LL N,M,W,Ans,Cnt,Tot,Left=-105,Mid,Right=105,C[Max<<1],X[Max<<1],Y[Max<<1],V[Max<<1],F[Max<<1];
inline LL Read(){
    LL X=0;char CH=getchar();bool F=0;
    while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
    while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
    return F?-X:X;
}
inline void Write(LL X){
    if(X<0)X=-X,putchar('-');
    if(X>9)Write(X/10);
    putchar(X%10+48);
}
bool Cmp(Node A,Node B){
    return A.V==B.V?A.C<B.C:A.V<B.V;
}
LL Find(LL X){
    return F[X]==X?X:Find(F[X]);
}
void Kruskal(){
    LL I,J,K;Ans=Cnt=0;
    Fp(I,1,N,1){
        F[I]=I;
    }
    Fp(I,1,M,1){
        G[I].Get(C[I],X[I],Y[I],V[I]);
        if(!G[I].C){
            G[I].V-=Mid;
        }
    }sort(G+1,G+1+M,Cmp);
    Fp(I,1,M,1){
        LL P=Find(G[I].X);
        LL Q=Find(G[I].Y);
        if(P!=Q){
            F[P]=Q;
            Ans+=G[I].V;
            if(!G[I].C){
                Cnt++;
            }
        }
    }
}
int main(){
    LL I,J,K;
    N=Read(),M=Read(),W=Read();
    Fp(I,1,M,1){
        X[I]=Read()+1;
        Y[I]=Read()+1;
        V[I]=Read();
        C[I]=Read();
    }
    while(Left<=Right){
        Mid=Left+Right>>1;
        Kruskal();
        if(Cnt>=W){
            Right=Mid-1;
            Tot=Ans+W*Mid;
        } else {
            Left=Mid+1;
        }
    }Write(Tot);
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324579096&siteId=291194637