【bzoj2654]】tree

给白色边都加上一个值,二分这个值,使得选取的白边数量减少

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

typedef long long LL;

#define N 100010

struct Node
{
    int x,y,z,c;
}e[N],a[N];

int n,m,need;

LL ans,cnt,tot;

int l,r,mid;

int f[N];

int cmp(Node a,Node b)
{
    return a.z==b.z ? a.c<b.c : a.z<b.z;
}

int find(int x)
{
    return f[x]!=x ? f[x]=find(f[x]) : f[x];
}

void kruskal()
{
    cnt=0,ans=0;
    int k=0;
    for (int i=1;i<=n;i++)
        f[i]=i;
    for (int i=1;k<n-1;i++)
    {
        int fa=find(e[i].x);
        int fb=find(e[i].y);
        if (fa!=fb)
        {
            f[fa]=fb;
            ans+=e[i].z;
            k++;
            if (!e[i].c)
                cnt++;
        }
    }
}

int main()
{
    scanf("%d%d%d",&n,&m,&need);
    for (int i=1;i<=m;i++)
        scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].z,&a[i].c),a[i].x++,a[i].y++;
    l=-1010,r=1010;
    while (l<=r)
    {
        mid=(l+r)>>1;
        for (int i=1;i<=m;i++)
            e[i]=a[i];
        for (int i=1;i<=m;i++)
            if (!e[i].c)
                e[i].z-=mid;
        sort(e+1,e+m+1,cmp);
        kruskal();
        if (cnt<need)
            l=mid+1;
        else
            r=mid-1,tot=ans+need*mid;
    }
    printf("%lld\n",tot);
    return 0;
}

  

时间: 2024-10-13 17:45:05

【bzoj2654]】tree的相关文章

【BZOJ2654】tree 二分+最小生成树

[BZOJ2654]tree Description 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V,E,need分别表示点数,边数和需要的白色边数. 接下来E行,每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色). Output 一行表示所求生成树的边权和. V<=50000,E<=100000,所有数据边权为[1,100]中的正整数. Sample Input 2 2 1

【bzoj2654】tree

Description 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V,E,need分别表示点数,边数和需要的白色边数. 接下来E行,每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色). Output 一行表示所求生成树的边权和. V<=50000,E<=100000,所有数据边权为[1,100]中的正整数. Sample Input 2 2 1 0 1 1 1 0 1 2 0

【bzoj2654】 tree

http://www.lydsy.com/JudgeOnline/problem.php?id=2654 (题目链接) 今天考试题,以为是神题不可做,直接放弃了..没想到这么水.. 题意:给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树.题目保证有解. solution  我们考虑把白边的权值增加,因为无论白边的权值增加多少,最小生成树中的白边不会改变.所以我们二分每次把所有白边的权值增加多少,按边权大小排序后克鲁斯卡尔看选出的白边是否大于need.统

二分+最小生成树【bzoj2654】: tree

2654: tree 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. 二分答案,然后跑最小生成树判断. 注意优先跑白色边. code: #include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int wx=500017; inline int read(){ int sum=0,f=1; ch

【BZOJ4987】Tree 树形DP

[BZOJ4987]Tree Description 从前有棵树. 找出K个点A1,A2,…,Ak. 使得∑dis(AiAi+1),(1<=i<=K-1)最小. Input 第一行两个正整数n,k,表示数的顶点数和需要选出的点个数. 接下来n-l行每行3个非负整数x,y,z,表示从存在一条从x到y权值为z的边. I<=k<=n. l<x,y<=n 1<=z<=10^5 n <= 3000 Output 一行一个整数,表示最小的距离和. Sample I

【POJ3237】Tree 树链剖分+线段树

[POJ3237]Tree Description You are given a tree with N nodes. The tree's nodes are numbered 1 through N and its edges are numbered 1 through N ? 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. Th

【Luogu1501】Tree(Link-Cut Tree)

[Luogu1501]Tree(Link-Cut Tree) 题面 洛谷 题解 \(LCT\)版子题 看到了顺手敲一下而已 注意一下,别乘爆了 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map>

【HDU5909】Tree Cutting(FWT)

[HDU5909]Tree Cutting(FWT) 题面 vjudge 题目大意: 给你一棵\(n\)个节点的树,每个节点都有一个小于\(m\)的权值 定义一棵子树的权值为所有节点的异或和,问权值为\(0..m-1\)的所有子树的个数 题解 考虑\(dp\) 设\(f[i][j]\)表示以\(i\)为根节点的子树中,异或和为\(j\)的子树的个数 很显然,每次合并就是两个\(dp\)值做\(xor\)卷积 那么直接用\(FWT\)优化就行了 #include<iostream> #inclu

点分治【bzoj1468】 Tree

点分治[bzoj1468] Tree Description 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K Input N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k Output 一行,有多少对点之间的距离小于等于k 点分治开始入门. 点分治,主要是解决形如:给你一棵树,求树上满足XX条件的点对的对数. 所以说应对的问题很多时候都和树形DP相同. 首先告诉自己,分治是高效的算法. 想一下,平时在面对普通的分治问题,每次肯定都是