UVa11324 The Largest Clique(强连通分量+DP)

题意:

看白书

要点:

求出强连通分量后缩成点,内部点数作为权,进行DAG的DP。

#include<iostream>
#include<stack>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1010;
vector<int> g[maxn],map[maxn];
int dfn[maxn],lowlink[maxn],sccno[maxn],dfs_clock,cnt,n,m;
bool instack[maxn];
stack<int> s;
int val[maxn],dp[maxn];

void dfs(int u)
{
	dfn[u]=lowlink[u]=++dfs_clock;
	s.push(u);
	instack[u]=true;
	for(int i=0;i<g[u].size();i++)
	{
		int v=g[u][i];
		if(!dfn[v])
		{
			dfs(v);
			lowlink[u]=min(lowlink[u],lowlink[v]);
		}
		else if(instack[v])
		{
			lowlink[u]=min(lowlink[u],dfn[v]);
		}
	}
	if(lowlink[u]==dfn[u])
	{
		cnt++;
		for(;;)
		{
			int x=s.top();s.pop();
			instack[x]=false;
			sccno[x]=cnt;
			if(x==u) break;
		}
	}
}
void Tarjan()
{
	dfs_clock=cnt=0;
	memset(instack,false,sizeof(instack));
	memset(dfn,0,sizeof(dfn));
	for(int i=1;i<=n;i++)
		if(!dfn[i])
			dfs(i);
}

int d(int u)
{
	if(dp[u])
		return dp[u];
	int ans=0;
	for(int i=0;i<map[u].size();i++)
	{
		int v=map[u][i];
		ans=max(ans,d(v));
	}
	return dp[u]=ans+val[u];
}

int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		for(int i=0;i<maxn;i++)
		{	
			g[i].clear();
			map[i].clear();	
		} 
		int u,v;
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d",&u,&v); 
			g[u].push_back(v);
		}
		Tarjan();
		memset(val,0,sizeof(val));
		memset(dp,0,sizeof(dp));
		//缩点
		for(int u=1;u<=n;u++)
		{
			val[sccno[u]]++;
			for(int j=0;j<g[u].size();j++)
			{
				int v=g[u][j];
				if(sccno[u]!=sccno[v])
					map[sccno[u]].push_back(sccno[v]);
			}
		}
		int ans=0;//注意可能cnt为0,此时结果只能为0 
		for(int i=1;i<=cnt;i++)
			ans=max(ans,d(i));
		printf("%d\n",ans);
	}
	return 0;
}


posted @ 2016-09-15 19:44  seasonal  阅读(86)  评论(0编辑  收藏  举报