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 }
View Code

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]
posted @ 2015-07-24 22:55  ChenThree  阅读(368)  评论(0编辑  收藏  举报