【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;
}

  

 

posted @ 2017-11-03 16:27  E-Valley  阅读(405)  评论(0)    收藏  举报