[BZOJ2654]tree 最小生成树+贪心
2654: tree
Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 2435 Solved: 1011
[Submit][Status][Discuss]
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
0 1 1 1
0 1 2 0
Sample Output
2
HINT
原数据出错,现已更新 by liutian,但未重测---2016.6.24
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 using namespace std; 8 int V,E,need,f; 9 struct data { 10 int u,v,val,c; 11 }e[100005]; 12 int fa[50005]; 13 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} 14 bool cmp(data t,data t1){ 15 return t.c==t1.c?t.val<t1.val:t.c<t1.c; 16 } 17 int ans=0; 18 int main() { 19 scanf("%d%d%d",&V,&E,&need); 20 for(int i=1;i<=E;i++) { 21 scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].val,&e[i].c); 22 } 23 sort(e+1,e+E+1,cmp); 24 for(int i=1;i<=V;i++) fa[i]=i; 25 int sum=0; 26 for(int i=1;i<=E;i++) { 27 int x=find(e[i].u),y=find(e[i].v); 28 if(x!=y) { 29 if(sum>=need){ 30 if(e[i].c==0) continue; 31 sum++; 32 fa[x]=fa[y]; 33 ans+=e[i].val; 34 } 35 else { 36 ans+=e[i].val; 37 fa[x]=fa[y]; 38 sum++; 39 } 40 } 41 if(sum==V-1) break; 42 } 43 printf("%d",ans); 44 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~