码迷,mamicode.com
首页 > 其他好文 > 详细

JZOJ3163. 排列

时间:2021-05-24 03:30:02      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:zoj   put   char   turn   not   二分图   匈牙利   范围   read   

题目大意

有一个\(n\)个数的排列, 给出\(m\)个限制诸如\(t_i, x_i, y_i, v_i\), 表示\([x_i, y_i]\)这个范围最大/最小是\(v_i\), 求最后所得的排列.
\(n <= 200\)

解题思路

非常裸的二分图匹配. 然而我太拉了并没有看出来.
对于一个限制, 显然在邻接矩阵中会删掉一些边. 匈牙利即可.

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 210
#define INF 0x3f3f3f3f
#define fo(i, a, b) for(int i = (a); i <= (b); ++i)
#define fd(i, a, b) for(int i = (a); i >= (b); --i)
using namespace std;
inline int max(int a, int b){return a > b ? a : b;}
inline int min(int a, int b){return a < b ? a : b;}
inline int read() // notice : 1. long long ? 2. negative ?
{
	int x = 0; char ch = getchar();
	while(ch < ‘0‘ || ch > ‘9‘)	ch = getchar();
	while(ch >= ‘0‘ && ch <= ‘9‘)	x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
	return x;
}
int n, m, mx[N], mn[N], ans[N];
bool mp[N][N], vis[N];
bool find(int u)
{
	fo(v, 1, n)
		if(!vis[v] && mp[u][v])
		{
			vis[v] = 1;
			if(!ans[v] || find(ans[v]))	return ans[v] = u, 1;
		}
	return 0;
}
int main()
{
//	freopen("perm.in", "r", stdin);
//	freopen("perm.out", "w", stdout);
	n = read(), m = read();
	fo(i, 1, n)	fo(j, 1, n)	mp[i][j] = 1;
	fo(i, 1, n)	mx[i] = INF;
	fo(i, 1, m)
	{
		int t = read(), l = read(), r = read(), v = read();
		fo(j, 1, l - 1)	mp[v][j] = 0;
		fo(j, l, r)	t == 1 ? mx[j] = min(mx[j], v) : mn[j] = max(mn[j], v);
		fo(j, r + 1, n)	mp[v][j] = 0;
	}
	fo(i, 1, n)
	{
		fo(j, 1, mn[i] - 1)	mp[j][i] = 0;
		fo(j, mx[i] + 1, n)	mp[j][i] = 0;
	}
	fo(i, 1, n)
	{
		fo(j, 1, n)	vis[j] = 0;
		if(!find(i))	return puts("-1"), 0;
	}
	fo(i, 1, n)	printf("%d ", ans[i]);
	return 0;
}

JZOJ3163. 排列

标签:zoj   put   char   turn   not   二分图   匈牙利   范围   read   

原文地址:https://www.cnblogs.com/Martin-MHT/p/14748619.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!