【珠宝】解题报告

来源:互联网 发布:网络口的最大数据来源 编辑:程序博客网 时间:2024/04/28 16:46
                                 珠宝(GEMS)     给一棵n 个结点的树,给每个点安排一个正整数编号,使得相邻点具有不同的编号,编号的 总和尽量小。 输入文件:   第一行:n(n<=50,000)   以下n-1 行,每行两个数u,v(1<=u,v<=n),表示u          和v 有一条边 输出文件:   仅一行,为最小编号和 SAMPLE INPUT 8 1  2 1  3 1  4 1  5 5  6 5  7 5  8 SAMPLE OUTPUT 11 

这道题我基本思路+骗分70分。


思路和正确的接近:

从叶节点开始,向根。叶节点尽量小。(*)

因此我想到了拓扑排序(不过因为是从叶节点开始,所以入度和初度交换了,感觉不是很科学),

节点“入度”为0的时刻即为他的编号。(这点其实是错误的,想得出反例)


第一次我用的栈维护的堆,后来因为一些自己做的测试数据有问题,因此改成了用队列维护。

结果过不了样例,我还是交了,居然70分。。(用栈的版本10分)

//=========================================================================

正确的思路:

从(*)处不同。

从(*)处想到后序遍历,因此可以想到树形DP,


引用:

看完题目,很自然地联想到树型DP,而且也不难得到状态表示方法。先根据输入的数据构造出一棵树,然后从树的叶子结点往上倒推。设F[I,J]表示以I为根的子树在I的编号为J时,可以得到的最小编号和。

状态转移方程为:F[I,J] = Min{∑F[I1, J1]} + J

其中I1表示I的一个子结点编号,J1为不同于J的一个自然数。


(这道题不能用四色定理,不知道为什么?因此J不能只开到4,开大一点20比较安全)

动规之上还必须用优化才能AC。。。。。。。。。。

//==========================================================================

骗分程序

//贪心 #include <iostream>using std::cout;//using std::cin;#include <cstdio>#include <cstdlib>const long oo = 0x7fff0000;struct ftv{long f;long t;};long n;ftv bian[100002];long chudu[50002];long start[50002];long top = 0;long cengci[50002];long que[100002];long l=0;long r=0;long long tot=0;int bigger(const void* a,const void* b){ftv* aa = (ftv*) a;ftv* bb = (ftv*) b;long aaa = aa->f;long bbb = bb->f;if (aaa>bbb) return 1;else if(aaa<bbb) return -1;else return -1;}int main(){freopen("gems.in","r",stdin);freopen("gems.out","w",stdout);scanf("%ld",&n);long t = 0;for (long i=1;i<n;i++){long u;long v;scanf("%ld%ld",&u,&v);t++;bian[t].f = u;bian[t].t = v;t++;bian[t].t = u;bian[t].f = v; chudu[bian[t].f]++;chudu[bian[t].t]++;}long m = (n-1)*2;qsort(bian+1,m,sizeof(ftv),&bigger);for (long i=1;i<=m;i++){if (start[bian[i].f]==0)start[bian[i].f]=i;}for (long i=1;i<n+1;i++){if (chudu[i]==1){que[++r] = i;cengci[i] = 1;tot++;}}while (l<r){long now = que[++l];chudu[now]=-1;for (long i=start[now];i<=m;i++){if (bian[i].f!=now) break;if (chudu[bian[i].t]>1){chudu[bian[i].t]--;if (cengci[bian[i].t]<cengci[now]+1){cengci[bian[i].t]=cengci[now]+1;}if (chudu[bian[i].t]==1){tot += cengci[bian[i].t];que[++r] = bian[i].t;}}}}cout << tot;return 0;}


原创粉丝点击