题解:CF1442C Graph Transpositions

求出 fuf_u 表示 11uu 的最少翻转次数,这一部分容易使用最短路处理。具体来说可以把每个状态拆成 gu,0/1g_{u,0/1} 表示 11uu,目前翻转次数为偶数或者奇数的最少翻转次数,跑最短路即可。

然后考虑每个点 uu 在最终最短路下的翻转次数,显然必然不会超过 fu+O(logn)f_u + O(\log n),这里直接取 fu+20f_u+20,那么每个点的翻转次数为 [fu,fu+20][f_u,f_u+20],直接跑分层图最短路即可。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
using namespace std;

const int N = 2e5 + 5;

int n, m;
using ll = long long;
const ll MOD = 998244353ll;

vector<pair<int, int>> G[N];
ll powe[N];
int f[N][2]; // 1->u:最小翻转次数
int f2[N][21];

struct Node2
{
	int u, x, d;
	Node2() = default;
	Node2(int u, int x, int d) : u(u), x(x), d(d) {}
	bool operator<(const Node2& x) const
	{
		return d > x.d;
	}
};

bool vis[N][2];
bool vis2[N][21];

int main()
{
	ios::sync_with_stdio(0), cin.tie(0);
	powe[0] = 1ll;
	for (int i = 1; i < N; i++) powe[i] = powe[i - 1] * 2ll % MOD;
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		int u, v;
		cin >> u >> v;
		G[u].emplace_back(make_pair(v, 0));
		G[v].emplace_back(make_pair(u, 1));
	}
	memset(f, 0x3f, sizeof f);
	auto dijkstra = [&]()
		{
			priority_queue<Node2> q;
			q.push(Node2(1, 0, 0));
			q.push(Node2(1, 1, 1));
			f[1][0] = 0;
			f[1][1] = 1;
			while (q.size())
			{
				auto [u, x, d] = q.top();
				q.pop();
				if (vis[u][x]) continue;
				vis[u][x] = 1;
				for (auto& [j, w] : G[u])
				{
					if (f[j][w] > f[u][x] + (x != w))
					{
						f[j][w] = f[u][x] + (x != w);
						q.push(Node2(j, w, f[j][w]));
					}
				}
			}
		};
	auto dijkstra2 = [&]
		{
			memset(f2, 0x3f, sizeof f2);
			priority_queue<Node2> q;
			for (int i = 0; i <= 20; i++) f2[1][i] = 0, q.push(Node2(1, i, 0));
			while (q.size())
			{
				auto [u, x, d] = q.top();
				q.pop();
				if (vis2[u][x]) continue;
				vis2[u][x] = 1;
				// 到u,翻转min(f[u][0],f[u][1])+x次
				int now = min(f[u][0], f[u][1]) + x;
				for (auto& [j, w] : G[u])
				{
					int nj = min(f[u][0], f[u][1]) + x + ((now & 1) != w) - min(f[j][0], f[j][1]);
					if (nj >= 0 && nj <= 20 && f2[j][nj] > f2[u][x] + 1)
					{
						f2[j][nj] = f2[u][x] + 1;
						q.push(Node2(j, nj, f2[j][nj]));
					}
				}
			}
		};
	dijkstra();
	dijkstra2();
	ll ans = (ll)1e18;
	int ri = 0;
	for (int i = 1; i <= 20; i++)
	{
		int k = min(f[n][0], f[n][1]) + i;
		ll cz = powe[k - 1];
		if (k - 1 <= 20 && f2[n][ri] - f2[n][i] > cz)
		{
			ri = i;
		}
	}
	int k = min(f[n][0], f[n][1]) + ri;
	ans = powe[k] - 1ll + f2[n][ri];
	cout << ans << "\n";
	return 0;
}
posted @ 2024-04-04 22:54  HappyBobb  阅读(3)  评论(0编辑  收藏  举报  来源