ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces Round #800 (Div. 1) C. Keshi in Search of AmShZ

2022-07-11 19:31:41  阅读:210  来源: 互联网

标签:Search DAG int tt Codeforces dijkstra Keshi hd DP


题目链接

对于有向图的问题,先想DAG该怎么做,这点还是没错的。对于DAG,就是一个按照拓扑序的DP,从n出发,每个点考虑删掉几条边即可(因为一定是删掉通往的点最差的那些边)。然后就一直在想有环怎么处理,但似乎不存在正确的解决方案。

这时候就应该考虑dijkstra的思路,即按照答案从小到大更新。沿用这个思路的条件是:每一条边的边权是可计算的,且没有负边。但刚才的DP思路,乍一看似乎每条边不是独立的;但会发现:每一种决策就是以一条边为基准,删去通向更劣的解边,而这个边数又恰好是在dijkstra的过程中可以计算的!!!

其实本质上是:把原本以为需要所有出边指向的点都算出来后,才能算出这个点的答案的问题;通过对DP转移方程的观察,转化为每条边都代表一种解的最短路问题,而这个解的计算恰好是在dijkstra中能够维护的。

对于有向图上的DP类问题,一般先考虑DAG怎么做,然后有两个方向:
1.考虑环(或强连通分量)该如何处理,如果可以特殊处理即可;
2.考虑用dijkstra的思路,按照答案的顺序更新,这用于每条边的贡献是可以在dijkstra的过程中计算的情况(边权有负数的情况用SPFA应该也可)。

留坑:找一些方向1可做的题目(以前肯定做过,印象中是环上DP之类的)

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m,hd[N],to[N],nx[N],du[N],tt;
void add(int u,int v){
	nx[++tt]=hd[u];
	to[hd[u]=tt]=v;
	du[v]++;
}
struct node{
	int u,d;
	bool operator <(const node& r) const{
		return d>r.d;
	}
};
int d[N];
priority_queue<node>q;
int main()
{
	cin>>n>>m;
	for(int u,v,i=1;i<=m;i++) scanf("%d%d",&v,&u),add(u,v);
	memset(d,0x3f,sizeof(d));
	d[n]=0;
	q.push((node){n,0});
	while(!q.empty()){
		node u=q.top();
		q.pop();
		if(u.d!=d[u.u]) continue;
		for(int e=hd[u.u];e;e=nx[e]){
			int v=to[e];
			if(u.d+du[v]<d[v]){
				d[v]=u.d+du[v];
				q.push((node){v,d[v]});
			}
			du[v]--;
		}
	}
	cout<<d[1]<<endl;
	return 0;
}

标签:Search,DAG,int,tt,Codeforces,dijkstra,Keshi,hd,DP
来源: https://www.cnblogs.com/szsz/p/16467598.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有