BZO 5450: 轰炸【缩点】【动态规划】

t a r j a n tarjan tarjan缩点,然后动态规划找最长链即可。

#include 
#include 
#include 
#include 
#include 
#define DB double
#define SG string
using namespace std;
const int Max=1e6+5;
const int Mod=1e9+7;
const int Inf=1e18;
struct Node{
	int Cnt,To[Max],Next[Max],Head[Max];
	void Insert(int X,int Y){
		To[++Cnt]=Y;Next[Cnt]=Head[X];Head[X]=Cnt;
	}
}G1,G2;
int Top,Stack[Max<<1];
int N,M,Tot,Num,Ans,DP[Max],Dfn[Max],Low[Max],Bel[Max],Size[Max];
inline int Read(){
	int X=0;char CH=getchar();bool F=0;
	while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
	while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
	return F?-X:X;
}
inline void Write(int X){
	if(X<0)X=-X,putchar('-');
	if(X>9)Write(X/10);
	putchar(X%10+48);
}
void Tarjan(int X){
	int I,J,K,Y;
	Dfn[X]=Low[X]=++Num;
	Stack[++Top]=X;
	for(I=G1.Head[X];I;I=G1.Next[I]){
		Y=G1.To[I];
		if(!Dfn[Y]){
			Tarjan(Y);
			Low[X]=min(Low[X],Low[Y]);
		} else if(!Bel[Y]){
			Low[X]=min(Low[X],Dfn[Y]);
		}
	}
	if(Dfn[X]==Low[X]){
		++Tot;
		while(true){
			Y=Stack[Top];
			Bel[Y]=Tot;Top--;
			if(X==Y){
				break;
			}
		}
	}
}
int GetDP(int X){
	if(~DP[X]){
		return DP[X];
	}DP[X]=0;int I;
	for(I=G2.Head[X];I;I=G2.Next[I]){
		DP[X]=max(DP[X],GetDP(G2.To[I]));
	}DP[X]+=Size[X];
	return DP[X];
}
int main(){
	int I,J,K;
	N=Read(),M=Read();
	for(I=1;I<=M;I++){
		int X=Read(),Y=Read();
		G1.Insert(X,Y);
	}
	for(I=1;I<=N;I++){
		DP[I]=-1;
	}
	for(I=1;I<=N;I++){
		if(Dfn[I]==0){
			Tarjan(I);
		}
	}
	for(I=1;I<=N;I++){
		Size[Bel[I]]++;
		for(J=G1.Head[I];J;J=G1.Next[J]){
			int Y=G1.To[J];
			if(Bel[I]!=Bel[Y]){
				G2.Insert(Bel[I],Bel[Y]);
			}
		}
	}
	for(I=1;I<=N;I++){
		if(!~DP[I]){
			Ans=max(Ans,GetDP(I));
		}
	}
	Write(Ans);
	return 0;
}

你可能感兴趣的:(动态规划与递推,图论-缩点,BZOJ)