bzoj2654

二分答案 给白色的边加上边权使刚刚好取到need条

这个二分是靠有右的。。。。

 1 #include<bits/stdc++.h>
 2 #define clr(a,x) memset(a,x,sizeof(a))
 3 #define rep(i,l,r) for(int i=l;i<r;i++)
 4 typedef long long ll;
 5 using namespace std;
 6 int read()
 7 {
 8     char c=getchar();
 9     int ans1=0,f=1;
10     while(!isdigit(c)){
11         if(c==‘-‘) f=-1;
12         c=getchar();
13     }
14     while(isdigit(c)){
15         ans1=ans1*10+c-‘0‘;
16         c=getchar();
17     }
18     return ans1*f;
19 }
20 struct edge{
21     int d,v,from,to,p;
22     inline bool operator <(const edge&A)const{
23         return v<A.v||(v==A.v&&p<A.p);
24     }
25 };
26 const int maxn=500005,maxm=100005;
27 edge e[maxm];
28 int f[maxn],n,m,need;
29 int find(int a)
30 {
31     return f[a]==a?f[a]:f[a]=find(f[a]);
32 }
33 int kruskal(int a)
34 {
35     int cnt=0,ans=0;
36     rep(i,0,n) f[i]=i;
37     rep(i,0,m){
38         if(!e[i].p) e[i].v=e[i].d+a;
39         else e[i].v=e[i].d;
40     }
41     sort(e,e+m);
42     rep(i,0,m){
43         if(find(e[i].from)!=find(e[i].to)){
44             f[find(e[i].from)]=find(e[i].to);
45             if(!e[i].p) cnt++;
46             ans+=e[i].v;
47         }
48     }
49     return cnt>=need?ans:-1;
50 }
51 int erfen(int l,int r)
52 {
53     if(l==r) return l;
54     int mid=(l+r+1)>>1;
55     int x=kruskal(mid);
56     if(x==-1) return erfen(l,mid-1);
57     return erfen(mid,r);
58 }
59 int main()
60 {
61     n=read(),m=read(),need=read();
62     rep(i,0,m){
63         e[i].from=read(),e[i].to=read(),e[i].d=read(),e[i].p=read();
64     }
65     int k=erfen(-500,500);
66     printf("%d\n",kruskal(k)-need*k);
67     return 0;
68 }

2654: tree

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 614  Solved: 228
[Submit][Status][Discuss]

Description

  给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。
  题目保证有解。

Input

  第一行V,E,need分别表示点数,边数和需要的白色边数。
  接下来E行
  每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色)。

Output

  一行表示所求生成树的边权和。

Sample Input

2 2 1
0 1 1 1
0 1 2 0

Sample Output

2

HINT

数据规模和约定

  0:V<=10

  1,2,3:V<=15

  0,..,19:V<=50000,E<=100000

  所有数据边权为[1,100]中的正整数。

Source

[Submit][Status][Discuss]

时间: 2024-12-08 22:29:31

bzoj2654的相关文章

【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 二分+最小生成树

[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

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

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

给白色边都加上一个值,二分这个值,使得选取的白边数量减少 #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,

二分+最小生成树【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

[转载]hzwer的bzoj题单

counter: 664BZOJ1601 BZOJ1003 BZOJ1002 BZOJ1192 BZOJ1303 BZOJ1270 BZOJ3039 BZOJ1191 BZOJ1059 BZOJ1202 BZOJ1051 BZOJ1001 BZOJ1588 BZOJ1208 BZOJ1491 BZOJ1084 BZOJ1295 BZOJ3109 BZOJ1085 BZOJ1041 BZOJ1087 BZOJ3038 BZOJ1821 BZOJ1076 BZOJ2321 BZOJ1934 BZOJ

[九省联考2018]林克卡特树(DP+wqs二分)

对于k=0和k=1的点,可以直接求树的直径. 然后对于60分,有一个重要的转化:就是求在树中找出k+1条点不相交的链后的最大连续边权和. 这个DP就好.$O(nk^2)$ 然后我们完全不可以想到,将best[k](选择k条链的答案)打表输出,更不可能然后作差分,发现得到的数组是递减的. 这说明:best[k]是一个上凸包. 于是我们可以二分一个斜率去切这个凸包(类似导数),根据切点横坐标与k的大小旋转直线(改变斜率). 考虑给你一个直线斜率k,怎么找到它和凸包的切点.实际上就相当于将这个凸函数减

WQS二分题集

WQS二分,一种优化一类特殊DP的方法. 很多最优化问题都是形如“一堆物品,取与不取之间有限制.现在规定只取k个,最大/小化总收益”. 这类问题最自然的想法是:设f[i][j]表示前i个取j个的最大收益,转移即可.复杂度O(n^2). 那么,如果在某些情况下,可以通过将问题稍作转化,变成一个不强制选k个的DP,而最后DP出来的最优解一定正好选了k个,那么问题就会简化很多. WQS二分就是基于这个思想. 首先考虑建一个二维坐标系,x轴是选的数的个数,y轴是最大收益,如果这个x-y图像有凸性,那么就