Codeforces Round #786 (Div. 3) G. Remove Directed Edges——树形dp+记忆化

思路参考
题目链接

思路

  • 题目要求删除一些边,要让最后每个点的入度,出度都小于最开始的情况,或者等于0。
    那么出度为1或者入度为1的边一定会被删掉,而且题目说明不存在重边和环,最后的结果一定是一条链。那么我们就树形dp,按照题目的约束去寻找最长的那一条链的长度即可。
  • d p [ u ] : dp[u] : dp[u] u u u 开头的链的长度, u u u 的出度大于1,才可更新 d p [ u ] dp[u] dp[u] u u u 的入度大于1才可向父亲转移,不然必定会被删掉。
  • 注意记忆化, d p [ u ] dp[u] dp[u] 被更新过后就没必要再搜一次了,不然会超时

AC代码

#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x; i<=y; ++i)
#define per(i,x,y) for(int i=x; i>=y; --i)
#define pushk push_back
#define popk pop_back
#define mem(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define ll long long
#define lp p<<1
#define rp p<<1|1
#define endl '\n'
using namespace std;
unordered_map<string,int> mp;
const int N = 2e5+9;
vector<int> g[N];
int in[N],out[N];
int dp[N];
void dfs(int u){
	//注意记忆化 
	if(dp[u]) return ;
	 dp[u]=1;
	if(g[u].size()==1) return ;
	for(auto & it : g[u]){
		dfs(it);
	    if(in[it]>1) dp[u]=max(dp[u],dp[it]+1);
	}
}
int main() {

	int n,m;
	cin>>n>>m;
	rep(i,1,m){
		int u,v;
		scanf("%d %d",&u,&v);
		in[v]++,out[u]++;
		g[u].pushk(v);
	}
	rep(i,1,n){
		 dfs(i);
	}
	int ans=0;
	rep(i,1,n) ans=max(ans,dp[i]);
	cout<<ans<<'\n';
	return 0;
}
posted @ 2022-08-28 08:42  翔村亲亲鸟  阅读(5)  评论(0编辑  收藏  举报