【縮點+tarjan(scc)】 uva 11324

題目大意:

在一張有向圖中,我們把有這樣性質的點的集合S稱之爲Clique(派系?)

對於任意在S中的兩個點x,y   存在x->y的路徑或(包含)存在y->x的路徑

 

思路:首先要明白,如果存在強連通分量,那麼在這個強連通分量裏的所有點他們都是一樣的,有你的肉就少不了我一杯羹。因此我們事實上可以把一個強連通分量縮成一個點,點權爲scc的大小。

然後我們又重新的到了一張無環的,有點權的有向圖。

 

然後我們所做的是找到一條【路徑】,上面包含的點權之和最大。

爲什麼是路徑不是子樹呢?因爲如果某點有兩個子節點,如果這兩個子節點毫無關係,則不滿組題目要求,如果有關係,那麼一定是在這條路徑上的。

 

#include <bits/stdc++.h>
#define CLR(arr) memset(arr,0,sizeof(arr)) 
using namespace std;
typedef long long ll;
const int maxn = 1e5+100; 

vector<int> G[maxn];

int pre[maxn];
int low[maxn];
int sccno[maxn];
int sccs[maxn];

int dfn;
int scc_cnt;

stack<int> S;

void dfs(int u)
{
	low[u] = pre[u] = ++dfn;
	S.push(u);
	for (int i = 0 ; i < G[u].size() ; ++i)
	{
		int v = G[u][i];
		if(!pre[v])
		{
			dfs(v);
			low[u] = min(low[u],low[v]);	
		}	
		else if (!sccno[v])
		{	low[u] = min(low[u],pre[v]); }
	}
		
	if(low[u] == pre[u])
	{
		scc_cnt++;
		while(1)
		{
			int x = S.top(); S.pop();
			sccno[x] = scc_cnt;
			sccs[scc_cnt]++;
			if(x == u) break;
		}	
	}
}

void find_scc(int n)
{
	CLR(pre);CLR(low);CLR(sccno);CLR(sccs);
	dfn = scc_cnt = 0;
	for (int i = 1 ; i <= n ; ++i)
		if(!pre[i])
			dfs(i); 
} 

vector<int> tree[maxn];

int dp[maxn];

void AddEdge(int u,int v)
{	G[u].push_back(v);	}

void AddDAG(int u,int v)
{	tree[u].push_back(v); }


int dps(int x)
{
	if(dp[x] != -1) return dp[x];
	
	dp[x] = sccs[x];
	for (int i = 0 ; i < tree[x].size() ; ++i)
	{
		int v = tree[x][i];
		dp[x] = max(dp[x],dps(v) + sccs[x])	;
	}	
	return dp[x];
}

int main()
{
	int T;
	cin >> T;
	int n,m;
	while(T--)
	{
		int x = 0 , y = 0; 
		cin >> n >> m;
		while(m--)
		{
			cin >> x >> y;
			AddEdge(x,y);
		}
		find_scc(n);
		for (int u = 1 ; u <= n ; ++u)
			for (int i = 0 ; i < G[u].size() ; ++i)
			{
				int v = G[u][i];
				if(sccno[v] != sccno[u])
					AddDAG(sccno[u],sccno[v]);
			}
		memset(dp,-1,sizeof(dp));
		int ans = 0;
		for (int i = 1 ; i <= scc_cnt ; ++i)
			ans = max(ans,dps(i));
		cout << ans << endl;
		for (int i = 0 ; i <= n ; ++i)
		{
			G[i].clear();
			tree[i].clear();
		}
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章