标签: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;
}
标签:zoj put char turn not 二分图 匈牙利 范围 read
原文地址:https://www.cnblogs.com/Martin-MHT/p/14748619.html