Codeforces 659F Polycarp and Hay 并查集

链接

Codeforces 659F Polycarp and Hay

题意

一个矩阵,减小一些数字的大小使得构成一个连通块的和恰好等于k,要求连通块中至少保持一个不变

思路

将数值从小到大排序,按顺序把与其相邻的加到并查集中。记录当前并查集中的个数,如果当前值能被K整除且总和超过了K,那么就可以以该点为中心输出了。

代码

#include <iostream>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <string>

#define LL long long
#define INF 0x3f3f3f3f
#define eps 1e-8

using namespace std;

struct node{
	int x, y;
	LL val;
};
node b[1000005];
int father[1000005];
int a[1005][1005];
bool vis[1005][1005];
LL num[1000005];
const int step[4][2] = { 1, 0, 0, 1, -1, 0, 0, -1 };
int n, m;
int get_father(int x){
	if (father[x] == x) return x;
	return father[x] = get_father(father[x]);
}
bool compare(node a, node b){
	return a.val > b.val;
}

void bfs(node u, LL k){
	queue<node> Q;
	int val = u.val;
	u.val = 1;
	Q.push(u);
	memset(vis, 0, sizeof(vis));
	vis[u.x][u.y] = true;
	int tag = k / (LL)val;
	int cnt = 1;
	bool flag = false;
	while (!Q.empty()){
		u = Q.front(); Q.pop();
		for (int i = 0; i < 4; ++i){
			int x = u.x + step[i][0];
			int y = u.y + step[i][1];
			if (x < 1 || x > n || y < 1 || y > m || a[x][y] < val || vis[x][y] || cnt >= tag) continue;
			node t = u;
			t.x = x, t.y = y;
			++cnt;
			vis[x][y] = true;
			if (cnt == tag){
				flag = true;
				break;
			}
			Q.push(t);
		}
		if (flag) break;
	}
	printf("YES\n");
	for (int i = 1; i <= n; ++i){
		for (int j = 1; j <= m; ++j){
			if (vis[i][j]){
				printf("%d ", val);
			}
			else{
				printf("0 ");
			}
		}
		printf("\n");
	}
}

int main(){
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
	LL k;
	while (~scanf("%d%d%I64d", &n, &m, &k)){
		int t = 0;
		for (int i = 1; i <= n; ++i){
			for (int j = 1; j <= m; ++j){
				scanf("%d", &a[i][j]);
				b[t].y = j;
				b[t].val = a[i][j];
				++t;
			}
		}
		for (int i = 0; i < n * m; ++i){
			father[i] = i;
			num[i] = 1;
		}
		sort(b, b + n * m, compare);
		for (int i = 0; i < n * m; ++i){
			int x, y;
			int p = (b[i].x - 1) * m + b[i].y;
			for (int j = 0; j < 4; ++j){
				x = b[i].x + step[j][0];
				y = b[i].y + step[j][1];
				if (x < 1 || x > n || y < 1 || y > m || a[x][y] < b[i].val) continue;
				int q = (x - 1) * m + y;
				int xf = get_father(p), yf = get_father(q);
				if (xf != yf){
					father[xf] = yf;
					num[yf] += num[xf];
					num[xf] = 0;
				}
			}
			int yf = get_father(p);
			if (k % b[i].val == 0 && num[yf] * b[i].val >= k){
				bfs(b[i], k);
				return 0;
			}
		}
		printf("NO\n");
	}
}

posted on 2016-06-03 15:38  张济  阅读(211)  评论(0编辑  收藏  举报

导航