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