题解CF260D Black and White Tree

题目:CF260D Black and White Tree

本题是一个基于贪心的构造,称之为“打擂法”。

我们把黑白两种颜色的节点分别放到两个数组里面并进行排序。

然后我们每次选两个来自不同集合的所剩权值最小的点进行连边,并把他们所剩的权值都减去连的边权。

接着让所剩权值为0的点下擂台,因为我们用不着它了,它没办法和后面的点进行配对连边。

最后处理剩下还没连的,随便和另一个集合里的点连0权边就行了。

这就是打擂法,适合于贪心类构造题。

upd:本题数据强度不够,我开始写的程序某处有个锅,把a和b打错了,竟然到#26才WA。。。

 

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define it register int
 4 #define il inline
 5 using namespace std;
 6 const int N=1000005;
 7 struct ky{
 8     int u,val;
 9     bool operator<(const ky&p)const{
10         return val<p.val;
11     }
12 }a[N],b[N];
13 int n,ca,cb,ci,vali;
14 bool tg[N];
15 il void fr(int &num){
16     num=0;char c=getchar();int p=1;
17     while(c<'0'||c>'9') c=='-'?p=-1,c=getchar():c=getchar();
18     while(c>='0'&&c<='9') num=num*10+c-'0',c=getchar();
19     num*=p;
20 }
21 int main(){
22     fr(n);
23     for(it i=1;i<=n;++i)
24         fr(ci),fr(vali),ci?a[++ca]=(ky){i,vali}:b[++cb]=(ky){i,vali};
25     sort(a+1,a+1+ca),sort(b+1,b+1+cb);
26     it i=1,j=1,minn;
27     while(i<=ca&&j<=cb)
28         minn=(a[i].val<b[j].val?a[i].val:b[j].val),printf("%d %d %d\n",a[i].u,b[j].u,minn),a[i].val-=minn,b[j].val-=minn,tg[a[i].u]=tg[b[j].u]=true,!a[i].val?++i:++j;
29     while(i<=ca){
30         if(!tg[a[i].u]) printf("%d %d 0\n",a[i].u,b[1].u),tg[a[i].u]=1;
31         ++i;
32     }
33     while(j<=cb){
34         if(!tg[b[j].u]) printf("%d %d 0\n",a[1].u,b[j].u),tg[b[j].u]=1;
35         ++j;
36     }
37     return 0;
38 }
View Code

 

posted @ 2019-10-08 09:57  kylin_xy  阅读(176)  评论(0编辑  收藏  举报