POJ1659-Frogs' Neighborhood

这题乍一看非常简单,很快就假了个思路:将所有点遍历一遍,当前没有完成配对的,直接往后找同样没完成配对的点进行配对。这个思路怎么想都是对的,但就是一直WARONG ANSWER。后面去POJ讨论区看了看,得知了hack数据

4
2 2 2 2

这个数据按照上面的思路输出的是NO,可以完成的前几组配对如下

1 2
1 3
2 3
4 寄

但实际上这个数据是可以完成配对的,规则如下

1 2
2 3
3 4
4 1

之所以假思路不能求出这个答案,是因为它每次都让前面的点相互配,将前面的点配完了,后面的点就没得配了。为了避免这个问题,需要将点放进堆中,排序依据是点在当前还需要配的点的数量。每次取需要配的点的数量最多的点,然后依次取需要配的数量数量第二多、第三多...的点跟它配,配完为止。

为什么这么配可以得到正解?感性分析一下:如果每次将配对了的两个点间连上一条无向边,最终就会得到一张没有重边无向图。题目的输入数据限制了图中每一个点的度,一个点所处的图越大,它的度能满足限制的几率也就越大。也就是说要尽可能地构造出更大地图。由于各个点的度是一定的,为了构造出更大的图,就要尽可能地提高每个连通子图的稀疏度,也就是说:在点一定的情况下,他们之间所连的边应尽可能少,这样就能分出更多的边给外面的其它点。因此需要以上面所说的顺序选点。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cctype>
using namespace std;
bool b[15][15];
int main()
{
    int _, n, i, j, a;
    scanf("%d", &_);
    while (_--)
    {
        scanf("%d", &n);
        priority_queue<pair<int, int> > pq;
        for (i = 1; i <= n; i++)
        {
            scanf("%d", &a);
            if (a)
                pq.push(make_pair(a, i));
        }
        for (i = 0; i <= n; i++)
            for (j = 0; j <= n; j++)
                b[i][j] = 0;
        bool flag = 0;
        while (!pq.empty())
        {
            pair<int, int> px = pq.top();
            pq.pop();
            if (pq.empty())
            {
                flag = 1;
                break;
            }
            stack<pair<int, int> > ps;
            while (px.first)
            {
                if (pq.empty())
                {
                    flag = 1;
                    break;
                }
                pair<int, int> pr = pq.top();
                pq.pop();
                if (b[pr.second][px.second])
                {
                    if (pq.empty())
                    {
                        flag = 1;
                        break;
                    }
                    ps.push(pr);
                    continue;
                }
                b[pr.second][px.second] = b[px.second][pr.second] = 1;
                pr.first--;
                px.first--;
                if (pr.first)
                    ps.push(pr);
            }
            if (flag)
                break;
            while (!ps.empty())
            {
                pq.push(ps.top());
                ps.pop();
            }
        }
        if (flag)
        {
            printf("NO\n\n");
            continue;
        }
        printf("YES\n");
        for (i = 1; i <= n; i++)
        {
            printf("%d", b[i][1]);
            for (int j = 2; j <= n; j++)
                printf(" %d", b[i][j]);
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}

 

posted @ 2022-01-21 19:12  zetaaaaaaaa  阅读(40)  评论(0)    收藏  举报