「NOI2009」变换序列

二分图最大匹配 #贪心

如果没有字典序最小的限制,直接二分图最大匹配就可以了

考虑怎么让字典序最小

倒序匹配左侧节点,对于每个节点,优先尝试字典序较小的方案,用 hungary 就行

另,如果用费用流,需要将斐波那契的第 \(10^4\) 位作为费用

// Author: xiaruize
#ifndef ONLINE_JUDGE
bool start_of_memory_use;
#else
#define debug(x)
#endif
#include <bits/stdc++.h>
using namespace std;
#ifndef ONLINE_JUDGE
clock_t start_clock = clock();
#endif
namespace __DEBUG_UTIL__
{
	using namespace std;
	/* Primitive Datatypes Print */
	void print(const char *x) { cerr << x; }
	void print(bool x) { cerr << (x ? "T" : "F"); }
	void print(char x) { cerr << '\'' << x << '\''; }
	void print(signed short int x) { cerr << x; }
	void print(unsigned short int x) { cerr << x; }
	void print(signed int x) { cerr << x; }
	void print(unsigned int x) { cerr << x; }
	void print(signed long int x) { cerr << x; }
	void print(unsigned long int x) { cerr << x; }
	void print(signed long long int x) { cerr << x; }
	void print(unsigned long long int x) { cerr << x; }
	void print(float x) { cerr << x; }
	void print(double x) { cerr << x; }
	void print(long double x) { cerr << x; }
	void print(string x) { cerr << '\"' << x << '\"'; }
	template <size_t N>
	void print(bitset<N> x) { cerr << x; }
	void print(vector<bool> v)
	{ /* Overloaded this because stl optimizes vector<bool> by using
		  _Bit_reference instead of bool to conserve space. */
		int f = 0;
		cerr << '{';
		for (auto &&i : v)
			cerr << (f++ ? "," : "") << (i ? "T" : "F");
		cerr << "}";
	}
	/* Templates Declarations to support nested datatypes */
	template <typename T>
	void print(T &&x);
	template <typename T>
	void print(vector<vector<T>> mat);
	template <typename T, size_t N, size_t M>
	void print(T (&mat)[N][M]);
	template <typename F, typename S>
	void print(pair<F, S> x);
	template <typename T, size_t N>
	struct Tuple;
	template <typename T>
	struct Tuple<T, 1>;
	template <typename... Args>
	void print(tuple<Args...> t);
	template <typename... T>
	void print(priority_queue<T...> pq);
	template <typename T>
	void print(stack<T> st);
	template <typename T>
	void print(queue<T> q);
	/* Template Datatypes Definitions */
	template <typename T>
	void print(T &&x)
	{
		/*  This works for every container that supports range-based loop
			i.e. vector, set, map, oset, omap, dequeue */
		int f = 0;
		cerr << '{';
		for (auto &&i : x)
			cerr << (f++ ? "," : ""), print(i);
		cerr << "}";
	}
	template <typename T>
	void print(vector<vector<T>> mat)
	{
		int f = 0;
		cerr << "\n~~~~~\n";
		for (auto &&i : mat)
		{
			cerr << setw(2) << left << f++, print(i), cerr << "\n";
		}
		cerr << "~~~~~\n";
	}
	template <typename T, size_t N, size_t M>
	void print(T (&mat)[N][M])
	{
		int f = 0;
		cerr << "\n~~~~~\n";
		for (auto &&i : mat)
		{
			cerr << setw(2) << left << f++, print(i), cerr << "\n";
		}
		cerr << "~~~~~\n";
	}
	template <typename F, typename S>
	void print(pair<F, S> x)
	{
		cerr << '(';
		print(x.first);
		cerr << ',';
		print(x.second);
		cerr << ')';
	}
	template <typename T, size_t N>
	struct Tuple
	{
		static void printTuple(T t)
		{
			Tuple<T, N - 1>::printTuple(t);
			cerr << ",", print(get<N - 1>(t));
		}
	};
	template <typename T>
	struct Tuple<T, 1>
	{
		static void printTuple(T t) { print(get<0>(t)); }
	};
	template <typename... Args>
	void print(tuple<Args...> t)
	{
		cerr << "(";
		Tuple<decltype(t), sizeof...(Args)>::printTuple(t);
		cerr << ")";
	}
	template <typename... T>
	void print(priority_queue<T...> pq)
	{
		int f = 0;
		cerr << '{';
		while (!pq.empty())
			cerr << (f++ ? "," : ""), print(pq.top()), pq.pop();
		cerr << "}";
	}
	template <typename T>
	void print(stack<T> st)
	{
		int f = 0;
		cerr << '{';
		while (!st.empty())
			cerr << (f++ ? "," : ""), print(st.top()), st.pop();
		cerr << "}";
	}
	template <typename T>
	void print(queue<T> q)
	{
		int f = 0;
		cerr << '{';
		while (!q.empty())
			cerr << (f++ ? "," : ""), print(q.front()), q.pop();
		cerr << "}";
	}
	/* Printer functions */
	void printer(const char *) {} /* Base Recursive */
	template <typename T, typename... V>
	void printer(const char *names, T &&head, V &&...tail)
	{
		/* Using && to capture both lvalues and rvalues */
		int i = 0;
		for (size_t bracket = 0; names[i] != '\0' and (names[i] != ',' or bracket != 0); i++)
			if (names[i] == '(' or names[i] == '<' or names[i] == '{')
				bracket++;
			else if (names[i] == ')' or names[i] == '>' or names[i] == '}')
				bracket--;
		cerr.write(names, i) << " = ";
		print(head);
		if (sizeof...(tail))
			cerr << " ||", printer(names + i + 1, tail...);
		else
			cerr << "]\n";
	}
	/* PrinterArr */
	void printerArr(const char *) {} /* Base Recursive */
	template <typename T, typename... V>
	void printerArr(const char *names, T arr[], size_t N, V... tail)
	{
		size_t ind = 0;
		for (; names[ind] and names[ind] != ','; ind++)
			cerr << names[ind];
		for (ind++; names[ind] and names[ind] != ','; ind++)
			;
		cerr << " = {";
		for (size_t i = 0; i < N; i++)
			cerr << (i ? "," : ""), print(arr[i]);
		cerr << "}";
		if (sizeof...(tail))
			cerr << " ||", printerArr(names + ind + 1, tail...);
		else
			cerr << "]\n";
	}
}
#ifndef ONLINE_JUDGE
#define debug(...) std::cerr << __LINE__ << ": [", __DEBUG_UTIL__::printer(#__VA_ARGS__, __VA_ARGS__)
#define debugArr(...) std::cerr << __LINE__ << ": [", __DEBUG_UTIL__::printerArr(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...)
#define debugArr(...)
#endif
#define int long long
#define ull unsigned long long
#define ALL(a) (a).begin(), (a).end()
#define pb push_back
#define mk make_pair
#define pii pair<int, int>
#define pis pair<int, string>
#define sec second
#define fir first
#define sz(a) int((a).size())
#define Yes cout << "Yes" << endl
#define YES cout << "YES" << endl
#define No cout << "No" << endl
#define NO cout << "NO" << endl
#define mms(arr, n) memset(arr, n, sizeof(arr))
#define rep(i, a, n) for (int i = (a); i <= (n); ++i)
#define per(i, n, a) for (int i = (n); i >= (a); --i)
int max(int a, int b)
{
	if (a > b)
		return a;
	return b;
}
int min(int a, int b)
{
	if (a < b)
		return a;
	return b;
}
const int INF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1000000007;
const int N = 2e4 + 10;

namespace MCMF
{
	const int MAXN = 3e4, MAXM = 3e4, INF = 0x7fffffff;
	int head[MAXN], cnt = 1;
	struct Edge
	{
		int to, w, c, next;
	} edges[MAXM * 2];
	inline void add(int from, int to, int w, int c)
	{
		edges[++cnt] = {to, w, c, head[from]};
		head[from] = cnt;
	}
	inline void addEdge(int from, int to, int w, int c)
	{
		add(from, to, w, c);
		add(to, from, 0, -c);
	}
	int s, t, dis[MAXN], cur[MAXN];
	bool inq[MAXN], vis[MAXN];
	queue<int> Q;
	bool SPFA()
	{
		while (!Q.empty())
			Q.pop();
		copy(head, head + MAXN, cur);
		fill(dis, dis + MAXN, INF);
		dis[s] = 0;
		Q.push(s);
		while (!Q.empty())
		{
			int p = Q.front();
			Q.pop();
			inq[p] = 0;
			for (int e = head[p]; e != 0; e = edges[e].next)
			{
				int to = edges[e].to, vol = edges[e].w;
				if (vol > 0 && dis[to] > dis[p] + edges[e].c)
				{
					dis[to] = dis[p] + edges[e].c;
					if (!inq[to])
					{
						Q.push(to);
						inq[to] = 1;
					}
				}
			}
		}
		return dis[t] != INF;
	}
	int dfs(int p = s, int flow = INF)
	{
		if (p == t)
			return flow;
		vis[p] = 1;
		int rmn = flow;
		for (int eg = cur[p]; eg && rmn; eg = edges[eg].next)
		{
			cur[p] = eg;
			int to = edges[eg].to, vol = edges[eg].w;
			if (vol > 0 && !vis[to] && dis[to] == dis[p] + edges[eg].c)
			{
				int c = dfs(to, min(vol, rmn));
				rmn -= c;
				edges[eg].w -= c;
				edges[eg ^ 1].w += c;
			}
		}
		vis[p] = 0;
		return flow - rmn;
	}
	int maxflow, mincost;
	inline void run(int s, int t)
	{
		MCMF::s = s, MCMF::t = t;
		while (SPFA())
		{
			int flow = dfs();
			maxflow += flow;
			mincost += dis[t] * flow;
		}
	}
} // namespace MCMF

int n;
int a[N];
vector<int> g[N];
bool vis[N];
int mat[N];

bool match(int x)
{
	if (vis[x])
		return false;
	vis[x] = true;
	for (auto v : g[x])
	{
		if (vis[v])
			continue;
		if (!mat[v] || match(mat[v]))
		{
			mat[v] = x;
			mat[x] = v;
			return true;
		}
	}
	return false;
}

void solve()
{
	cin >> n;
	rep(i, 0, n - 1)
	{
		cin >> a[i];
		int p = (i + a[i]) % n, q = (i - a[i] + n) % n;
		if (p > q)
			swap(p, q);
		g[i].push_back(p + n);
		g[i].push_back(q + n);
		debug(g[i]);
	}
	int cnt = 0;
	per(i, n - 1, 0)
	{
		mms(vis, 0);
		cnt += match(i);
		debug(cnt);
	}
	// debug(cnt);
	if (cnt != n)
	{
		cout << "No Answer" << endl;
		return;
	}
	rep(i, 0, n - 1) cout << mat[i] - n << ' ';
}

#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif

signed main()
{
	freopen("transform.in","r",stdin);
	freopen("transform.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int testcase = 1;
	// cin >> testcase;
	while (testcase--)
		solve();
#ifndef ONLINE_JUDGE
	cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
	cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
	return 0;
}
posted @ 2024-03-28 15:27  xiaruize  阅读(18)  评论(0)    收藏  举报