SDOJ 3696 Tree

描述

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

输入

第一行V,E,need分别表示点数,边数和需要的白色边数。

接下来E行

每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色)

输出

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

样例输入

2 2 1
0 1 1 1
0 1 2 0

样例输出

2

数据规模和约定

0%:V<=10

30%:V<=15

100%:V<=50000,E<=100000

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

.......................

太困了!!!!!!

先贴个代码 明天再写思路

耶~

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #define N 50010
 7 using namespace std;
 8 int n,m,k;
 9 int first[N],cnt;
10 int a[N*2],b[N*2],c[N*2],d[N*2];
11 int fa[N],sum;
12 struct node
13 {
14     int u,v,w,nxt;
15     int col;
16 }e[N*2];
17 void ade(int x,int y,int z,int c,int i)
18 {
19     e[i].u=x;
20     e[i].v=y;
21     e[i].w=z;
22     e[i].col=c;
23 }
24 bool cmp(const node &p,const node &q)
25 {
26     if(p.w!=q.w)
27           return p.w<q.w;
28     return p.col<q.col;
29 }
30 int la(int x)
31 {
32     if(fa[x]!=x) fa[x]=la(fa[x]);
33     return fa[x];
34 }
35 bool kruskal(int x)
36 {
37     for(int i=0;i<n;i++) fa[i]=i;
38     for(int i=1;i<=m;i++)
39     {
40         ade(a[i],b[i],c[i],d[i],i);
41         if(d[i]==0) e[i].w+=x;
42     }
43     sort(e+1,e+m+1,cmp);
44     sum=0;
45     int num=0,ans=0;
46     for(int i=1;i<=m;++i)
47     {
48         if(la(e[i].u)!=la(e[i].v))
49         {
50             num++;
51             sum+=e[i].w;
52             fa[la(e[i].u)]=la(e[i].v);
53             if(e[i].col==0) ans++;
54         }
55         if(num==n-1) break;
56     }
57     if(ans>=k)
58         return true;
59     return false;
60 }
61 int main()
62 {
63     scanf("%d%d%d",&n,&m,&k);
64     for(int i=1;i<=m;i++)
65         scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
66     int l=-100,r=100,mid;
67     while(l<r)
68     {
69         mid=(l+r+1)>>1;
70         if(kruskal(mid)) l=mid;
71         else r=mid-1;
72     }
73     kruskal(l);
74     printf("%d",sum-k*l);
75     return 0;
76 }
View Code

猜你喜欢

转载自www.cnblogs.com/kylara/p/9440303.html