现在的位置: 首页 > 综合 > 正文

2012多校联合(3)

2013年01月01日 ⁄ 综合 ⁄ 共 2358字 ⁄ 字号 评论关闭

HDU 4322 Candy

题意:有N颗糖果和M个小孩,老师现在要把这N颗糖分给这M个小孩。每个小孩i对每颗糖j都有一个偏爱度Aij,如果他喜欢这颗糖,Aij = k,否则Aij = 1。小孩i觉得高兴当且仅当ΣCij×Aij >= Bi,j=1,2,…,N,若他分得了糖j,Cij = 1,否则Cij
= 0。问能否合理分配这N颗糖,使得每个小孩都觉得高兴。

体会:一开始看M、N都小于13,而且大家都wa爆虽然想到了费用流做法但是一次构图的做法没敢继续想下去,于是在想2^13枚举构图的做法。后来证明一开始的方向是正确的,不应该被坑爹的数据范围吓住。

解法:由于每块糖都与1和k两种欢乐值,因此应该尽可能分配欢乐值为k的糖果,对于剩余的值可随意选择填满(与是否喜欢无关),对于每个人要尽可能分配bi/k块喜欢的糖,这个容量就是bi/c,对结果的贡献为k。对于剩余的bi%k可选择一块喜欢的糖或者bi%k块不喜欢的糖(这里怎么控制没有想到)。bi%c(>1)的也是可以用一个能让这个小孩欢喜的糖来贡献,但是其贡献只为bi%c。对于小孩来说,最大费用最大流后,糖分配的贡献值为最大费用,剩余糖就是(n-最大流),然后用这些糖去填不满的,只要满足总和大于Σbj。就可以分配了。

具体建模方案:

(s,i,1,0);

(i,j,1,0);

(j,t,bj/k,k);

If(bj%k>1)

(j,t,1,bj%k)

Ans = 费用 + N – 最大流 >= Σbj  则满足要求

费用不仅仅可以表示耗费,也可以表示贡献,或许还可以表示其它属性,要灵活使用。

HDU 4324 Triangle Love

题意:2000个点的竞赛图,保证任意两点间仅有一条有向边,问是否存在一个三元环。

解法很多,一一列举:

如果把任意有公共顶点的两边构成的图形看做一个角,可将角分为是b的和不是b的(用a类表示),把任意三条边看做一个三角形,可将三角形分为x、y两种。对于每个顶点入度为in出度为out则共有in*out种b种角,由于是竞赛图,因此有C(n,2)-in*out种a种角,根据3x+y=b,2y=a,因此x=(b-a/2)/3,即可求出三元环的个数。

对于有向三元环,我们知道找到:A->B->C->A ,B->C->A->B ,C->A->B->C 是一样的,这给0(n^2)的算法提供了基础。
对于每次枚举i,我们在(0~i-1)的范围看下有多少个i指向的点(剩下的就是指向i的点),同时算下i指向的点的出度和。就可以知道这些 i指向的点 指向 指向i的点(剩下的点)的数目,如果 num * (num - 1) / 2 < sumout 那么就是被指向的点有指出去了,这样就形成了3元环。否则,剩下的就是更新下出度即可,继续执行下一个节点。

结论:对于一个竞赛图,若存在n元环,一定存在一个n-1元环或者三元环,此题可以一遍拓扑排序判环求解即只需要找到一个环,就必定存在三元环。证明如下:
假设存在一个n元环,因为a->b有边,b->a必定没边,反之也成立 所以假设有环上三个相邻的点a-> b-> c,那么如果c->a间有边,就已经形成了一个三元环,如果c->a没边,那么a->c肯定有边,这样就形成了一个n-1元环。。。。 所以只需证明n为4时一定有三元环即可,显然成立

Hdu 4323 Magic Number

给出一个字典,查询某个词与字典中编辑距离小于k的单词的个数。

普通的dp就可搞,这里顺便学了个BKTree,此数据结构的用处暂时没想出来,所以只是随便实现了一下,没有仔细研究。

参考资料:Matrix67的《编辑距离、拼写检查与度量空间:一个有趣的数据结构》

 class BK {
    	int maxn = 12;// 最大距离
        class node {
            node ch[];
            String key;
            int count;
            node(String s) {
                key = s;
                count = 1;
                ch = new node[maxn];
            }
        }
        node root;
        int dp[][] = new int[maxn][maxn];
        int dis(String a, String b) {
            int n = a.length();
            int m = b.length();
            for (int i = 0; i < maxn; i++)
                dp[0][i] = dp[i][0] = i;
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= m; j++) {
                    int flag = 1;
                    if (a.charAt(i - 1) == b.charAt(j - 1))
                        flag = 0;
                    dp[i][j] = Math.min(
                            Math.min(dp[i - 1][j], dp[i][j - 1])+1,
                            dp[i - 1][j - 1] + flag);
                }
            }
            return  dp[n][m];
        }
        void init() {
            root = null;
        }
        void insert(String s, node r) {            
            int d = dis(r.key, s);
            if (d == 0){
                r.count++;
                }
            else if(r.ch[d]==null)
                r.ch[d]=new node(s);
            else
                insert(s, r.ch[d]);
        }

        void insert(String s) {
            if(root==null)
                root= new node(s);
            else
            insert(s, root);
        }

        int query(String s, int n) {
            return query(root, s, n);
        }
        int query(node r, String s, int n) {
            int ans = 0;
            if (r == null)
                return 0;
            int d = dis(r.key, s);
            if (d <= n)
                ans += r.count;

            int a = Math.max(d - n, 1), b = Math.min(maxn-1, d + n);
            for (int i = a; i <= b; i++)
                ans += query(r.ch[i], s, n);
            return ans;
        }
    }


【上篇】
【下篇】

抱歉!评论已关闭.