ζ

POJ1659-Frogs' Neighborhood

    题解

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

1
2
4
2 2 2 2

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

1
2
3
4
1 2
1 3
2 3
4 寄

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

1
2
3
4
1 2
2 3
3 4
4 1

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#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;
}
页阅读量:  ・  站访问量:  ・  站访客数: