POJ 1659 Frogs' Neighborhood

 /*
一开始用了带剪枝的搜索,不知道为什么一直WA

后来改成havel贪心定理才AC,有兴趣的拿去研究下下面这个搜索为什么过不了
#include <iostream>
#define MAX_S 600
#define MAX_N 9
using namespace std;

int states[MAX_N + 1][MAX_S + 1];
int curStates[MAX_N + 1];
int expv[MAX_N + 1];
int num[MAX_N + 1];
int n;
void getExp()
{
    expv[0] = 1;
    for(int i = 1; i <= MAX_N; i++)
        expv[i] = expv[i - 1] * 2;
}
void getAllState(int pos, int num, int state)
{
    if(pos == n)
    {
        states[num][0]++;
        states[num][states[num][0]] = state;
        return;
    }
    getAllState(pos + 1, num + 1, state | expv[pos]);
    getAllState(pos + 1, num, state);
}

bool can;
void solve(int pos, int curStates[])
{
    if(pos == n)
    {
        can = true;
        return;
    }
    int p, k;
    for(p = 1; p <= states[num[pos]][0] && !can; p++)
    {
        int curS = states[num[pos]][p];
        if(curS & expv[pos]) continue;
        for(k = 0; k < pos; k++)
        {
            int can1 = curStates[k] & expv[pos];
            int can2 = curS & expv[k];

            //剪枝
            if((can1 != 0 && can2 == 0) || (can1 == 0 && can2 != 0))
                break;
        }
        if(k < pos) continue;
        curStates[pos] = curS;
        solve(pos + 1, curStates);
    }
}
int main()
{
    int caseN, i, j;
    getExp();
    scanf("%d", &caseN);
    while(caseN--)
    {
        scanf("%d", &n);
        memset(states, 0, sizeof(states));
        memset(curStates, 0, sizeof(curStates));
        getAllState(0, 0, 0);
        for(i = 0; i < n; i++) scanf("%d", &num[i]);
        can = false;
        solve(0, curStates);
        if(can)
        {
            printf("YES/n");
            for(i = 0; i < n; i++)
            {
                for(j = 0; j < n; j++)
                {
                    if(j != 0) printf(" ");
                    if(curStates[i] & expv[j]) printf("1");
                    else printf("0");
                }
                printf("/n");
            }
        }
        else printf("NO/n");
        printf("/n");
    }
    return 0;
}
*/

 

/*havel定理版本*/

#include <iostream>
#include <algorithm>
#define MAX_S 600
#define MAX_N 9
using namespace std;


int n;
struct node
{
    int idseq, degree;
    bool connect[MAX_N + 1];
}nodes[MAX_N + 1];

bool compare1(const node &n1, const node &n2)
{
    return n1.degree >= n2.degree;
}
bool compare2(const node &n1, const node &n2)
{
    return n1.idseq <= n2.idseq;
}

bool havel()
{
    int i, j, deg, fid, tid;
    for(i = 0; i < n; i++)
    {
        sort(&nodes[i], &nodes[i] + n - i, compare1);
        deg = nodes[i].degree;
        fid = nodes[i].idseq;
        if(n - 1 - i < deg) return false;
        for(j = i + 1; j <= i + deg; j++)
        {
            tid = nodes[j].idseq;
            nodes[i].connect[tid] = true;
            nodes[j].connect[fid] = true;
            nodes[j].degree--;
            if(nodes[j].degree < 0) return false;
        }
    }
    return true;
}
int main()
{
    int caseN, i, j;
    scanf("%d", &caseN);
    while(caseN--)
    {
        scanf("%d", &n);
        for(i = 0; i < n; i++)
        {
            scanf("%d", &nodes[i].degree);
            nodes[i].idseq = i;
            memset(nodes[i].connect, 0, sizeof(nodes[i].connect));
        }
        
        bool can = havel();
        sort(nodes, nodes + n, compare2);
        if(can)
        {
            printf("YES/n");
            for(i = 0; i < n; i++)
            {
                for(j = 0; j < n; j++)
                {
                    if(j != 0) printf(" ");
                    if(nodes[i].connect[j]) printf("1");
                    else printf("0");
                }
                printf("/n");
            }
        }
        else printf("NO/n");
        printf("/n");
    }
    return 0;
}

 

/*补充havel定理相关内容(摘自http://203.208.39.132/search?q=cache:FizGQJ-6NaoJ:hi.baidu.com/roba/blog/item/0732d01645a9ec1b972b4380.html+harvel+%E5%AE%9A%E7%90%86&cd=1&hl=zh-CN&ct=clnk&gl=cn&st_usg=ALhdy2_AdwSZ0NavagiEda9fBTYrC38mXg):

给定一个非负整数序列{d1,d2,...dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化。进一步,若图为简单图,则称此序列可简单图化。

可图化的判定比较简单:d1+d2+...dn=0(mod2)。关于具体图的构造,我们可以简单地把奇数度的点配对,剩下的全部搞成自环。

可简单图化的判定,有一个Havel定理,是说: 我们把序列排成不增序,即d1>=d2>=...>=dn,则d可简单图化当且仅当d'=(d2-1, d3-1, ... d(d1+1)-1, d(d1+2), d(d1+3), ... dn)可简单图化。实际上就是说,我们把d排序以后,找出度最大的点(设度为d1),把它和度次大的d1个点之间连边,然后这个点就可以不管了,一直继续这个过程,直到建出完整的图,或出现负度等明显不合理的情况。

*/

你可能感兴趣的:(POJ 1659 Frogs' Neighborhood)