专栏文章

题解:CF1693C Keshi in Search of AmShZ

CF1693C题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minadtge
此快照首次捕获于
2025/12/01 23:10
3 个月前
此快照最后确认于
2025/12/01 23:10
3 个月前
查看原文
我们倒着思考,考虑一种类似 DP 的方法:设 fuf_u 表示从点 uu 走到目标点的最小代价,则有 fu=minvnxtu(fv+vnxtu[fv>fv]+1)f_u=\min\limits_{v \in nxt_u} (f_v+\sum\limits_{v' \in nxt_u}[f_{v'} > f_v] + 1)
这个式子比较好理解:我们考虑我们最后一定会选一条边走出这个点,钦定当前选定的边是 uvu \to v,则首先把 fv>fvf_{v'}>f_v 的边 uvu \to v' 封住一定是不劣的。然后由于现在要花时间向外走一步,故代价要加上 11。这样做就出现了一个问题:我们的图是存在环的,无法确定更新的先后顺序以在一次遍历中确定最终 ff 的值,而每次暴力遍历所有点和其出边直到不能再更新 ff 的值又会导致时间复杂度不可接受。
注意到 DP 值非负,考虑 Dijkstra trick 优化该 DP。我们从终点 nn 开始采用类似 Dijkstra 的方式从小到大确定 ff 的值,这样我们就能在 O(mlogm)O(m \log m) 的时间复杂度内求解完所有的 DP 值。同时这样做我们 \sum 内的值也是容易计算的。
代码:
CPP
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define pii pair <int , int>
#define pb push_back
#define fi first
#define se second
#define fastio ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0);
using namespace std;
const int MAXN = 2e5 + 10 , INF = 0x3f3f3f3f;
int n , m;
int f[MAXN] , cnt[MAXN];
bitset <MAXN> vis;
struct node
{
	int id;
	int val;
	bool operator < (const node &x) const {return val > x.val;}
};
vector <int> a[MAXN];
priority_queue <node> q;
void solve()
{
	q.push({n , 0});
	while(!q.empty())
	{
		auto now = q.top();
		q.pop();
		if(vis[now.id]) continue;
		vis[now.id] = 1;
		f[now.id] = now.val;
		for(int i : a[now.id])
		{
			if(vis[i]) continue;
			q.push({i , now.val + cnt[i]});
			cnt[i]--;
		}
	}
	return;
}
int main()
{
	fastio;
	cin >> n >> m;
	for(int i = 1 ; i <= m ; i++)
	{
		int u , v;
		cin >> u >> v;
		a[v].pb(u);
		cnt[u]++;
	}
	memset(f , INF , sizeof(f));
	solve();
	cout << f[1];
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...