思路参考
题目链接
思路
- 题目要求删除一些边,要让最后每个点的入度,出度都小于最开始的情况,或者等于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;
}