【2017.11.3】noip赛前集训 | T0 Lighthouses【玄学】、T1 (%%%) lyx (dalao)【记忆化递推、生物学】
T0 Lighthouses
【题意】
大洋上共有 N 个岛屿,从 1 到 N 标号。与广袤的大海相比,我们可以认为每个岛都只是平面上的一个点。给定所有岛屿的笛卡尔坐标,坐标系 X 轴指向东,Y 轴指向北。
你需要照亮所有的岛屿。为此,你可以在某些岛屿上修建灯塔。每个岛屿至多只能建一座灯塔。每个灯塔可以照亮以它为原点的坐标系的一个象限,即东北、西北、西南、东南的其中之一。注意如果一个岛屿落在光照的边缘,也被认为被照亮了,这意味着修建灯塔的岛屿总是被照亮的。
请你找出一个照亮所有岛屿所需灯塔数(记为 L)最小的方案.
【数据范围】
对于20%的数据 1 ≤ N,T ≤ 10,
对于100%的数据 :1 ≤ T ≤ 1000;1 ≤ N ≤ 10^5 ; 0 ≤ |Xi |, |Yi | ≤ 10^9;
各组数据中 N 的和不超过 5 × 10^5
【题解】
根据玄学的考虑,我们知道:
最多建两座灯塔即可以照亮全部的岛屿。
而一座灯塔照亮全部的情况很容易判断。
#include <cstdio>
#include <algorithm>
#include <cstring>
const int MAXN = 1e5 + 7, INF = 0x7fffffff;
int T, n, a[MAXN][2], maxx, maxy, minx = INF, miny = INF;
int main() {
// freopen("Lighthouses.in", "r", stdin);
// freopen("Lighthouses.out", "w", stdout);
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
memset(a, 0, sizeof(a));
maxx = 0, maxy = 0, minx = INF, miny = INF; // !!!!!!!!!!!!!!!!!!初始化
for (int i = 1; i <= n; i++) {
scanf("%d%d", &a[i][0], &a[i][1]);
minx = std::min(minx, a[i][0]);
miny = std::min(miny, a[i][1]);
maxx = std::max(maxx, a[i][0]);
maxy = std::max(maxy, a[i][1]);
}
bool ok = 0;
for (int i = 1; i <= n; i++) {
if ((a[i][0] == minx && a[i][1] == miny) || (a[i][0] == minx && a[i][1] == maxy)
|| (a[i][0] == maxx && a[i][1] == miny) || (a[i][0] == maxx && a[i][1] == maxy))
ok = 1;
}
printf(ok ? "1\n" : "2\n");
}
return 0;
}
T2 卢学魔
【题意】
给你 n 个物种和 m 条能量流动关系,求其中的食物链条数。 物种的名称为从 1 到 n 编号
M 条能量流动关系形如 a1b1 a2b2 a3b3 ...... am-1bm-1 ambm 其中 aibi 表示能量从物种 ai 流向物种 bi

【数据范围】
1<=N<=100000
0<=m<=200000
【题解】
1.能量在食物网中的流动是单向的,所以保证了这个图是一个有向无环图。
2.在这个图中没有入度的点就是生产者(不止一个),没有出度并且不是生产者的点就是 最高级消费者。
食物链的定义就与生物书上一样。有一个要注意的地方就是生产者在那 里,没有人吃是不算一条食物链的。食物链的条数事实上就是从生产者到最高级消费者 的路径总数。 弄懂题意了之后建逆图,随便递推一下就可以了时间复杂度 O(n+m)。如果不递推直接 dfs 数的话只有 70 分,记忆化搜索也可以吧,没试过。 一道大水题细节注意一下就可以了。
#include <cstdio>
#include <queue>
const int MAXN = 2e5 + 7;
int n, m, ans, f[MAXN];
int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch > '9' || ch < '0') (ch == '-') && (f = -1), ch = getchar();
while (ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
return x * f;
}
struct Edge;
struct Node {
Edge *last;
int in, out, ma;
bool root;
} node[MAXN];
struct Edge {
Node *from, *to;
Edge *next;
Edge(Node *from, Node *to) : from(from), to(to), next(from->last) {}
};
void addE(int x, int y) {
node[x].last = new Edge(node + x, node + y);
node[x].out++;
node[y].in++;
}
std::queue<Node *> q;
//void dfs(int s) { // 60分的dfs,应该是70分的,第七个点不知道为什么RE了,衰~
// if (!node[s].out) ans++;
//
// for (Edge *e = node[s].last; e; e = e->next) {
// dfs(e->to->ma);
// }
//}
int main() {
freopen("lyx.in", "r", stdin);
freopen("lyx.out", "w", stdout);
n = read();
m = read();
for (int i = 1; i <= n; i++) node[i].ma = i;
for (int i = 1; i <= m; i++) {
int x = read(), y = read();
addE(y, x);
}
for (int i = 1; i <= n; i++) {
if (!node[i].in && !node[i].out) continue;
if (!node[i].in) f[i] = 1, q.push(node + i);
if (!node[i].out && node[i].in) node[i].root = 1;
}
while (!q.empty()) {
Node *v = q.front();
q.pop();
for (Edge *e = v->last; e; e = e->next) {
f[e->to->ma] += f[v->ma];
e->to->in--;
if(!e->to->in) q.push(e->to);
}
}
for (int i = 1; i <= n; i++) {
if (node[i].root) ans += f[i];
}
printf("%d", ans);
return 0;
}

浙公网安备 33010602011771号