Codeforces Round #800 (Div. 1) C. Keshi in Search of AmShZ
作者:互联网
对于有向图的问题,先想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