codility 上的问题之八 Eta 2011

这个题太长了……但是解法又出奇的水。 有兴趣的读原文去,我还是把题目化简一下比较好。M个节点的无向图,M是偶数。这个无向图是这么来的,首先它是树,然后这个树的节点要么只和一个节点相连,要么和 3个节点相连…… 度为1的是叶子,我们把一个叶子当做根,拎上去……,那么度为3的是二叉树的中间节点。所有的节点要么是叶子,要么有两个孩子,就是这么一个特殊的树。然后把所有的叶子按顺序连称一个圈包括我们规定的根)。问最终形成的图,有多少条哈密尔顿回路。问题的输入是原来那个树的dfs序列……M是节点数的话 输入长度N = 2 *( M - 1)范围在[4..200000],数组里的元素大小是[0..(M-1)]。

输出要求: 

如果哈密尔顿圈的数超过10^8,输出-1。

如果输入非法,输出-2。

合法性: (1) 每条路连接两个不同的节点

                 (2) 每个节点经过一次或者3次。

                 (3) 每条路走了两次

复杂度要求:时间O(N),空间O(N)。

分析:  首先合法性判断是说判断给定的那个dfs序列是不是一棵满足要求的树,我们自己弄个堆栈判断一下就好了,O(N)。这个题的时间复杂度就在这里,空间复杂度也在这里。但是这个题最难的不在这里……,最难的在于哈密尔顿圈的个数。

我曾经看了一个分析挺好的。。。。




红得表示经过,A是父亲,B C是子树,总之就是孩子的走法决定了上层的走法也唯一,然后这个子树考虑完之后可以缩成点…… 

总之,无论多少个节点,只有3个哈密尔顿圈…… 所以那些输入神马的都是浮云……


代码:

// you can also use includes, for example:
// #include <algorithm>
#include <vector>
int solution(const vector<int> &A) {
    // write your code here...
   int n = A.size(), m = (n >> 1) + 1,i,invalid = m;
   vector<int> num,path;
   num.resize(m, 0);
   for (i = 0; i < n; ++i) {
       if ((i) && (A[i] == A[i - 1])) {
           return -2;
       }
       switch(++num[A[i]]) {
       case 1:
           path.push_back(A[i]);
           --invalid;
           break;
       case 2:
           if ((path.size() < 2) || (path[path.size() - 2] != A[i])) {
               return -2;
           }
           ++invalid;
           path.pop_back();
           break;
       case 3:
           if ((path.size() < 2) || (path[path.size() - 2] != A[i])) {
               return -2;
           }
           --invalid;
           path.pop_back();
           break;
       default:
           return -2;
       }
   }
   return invalid?(-2):3;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值