HAOI2010軟件安裝--強連通縮點+樹型dp

今天覆習了一下強連通分量(顯然之前就沒學得好)。

強連通分量一般用在環套樹的有向圖中,先把每個強連通分量縮點,然後把它當做普通樹處理。

雙聯通分量也順便看了一下,但是感覺用處遠遠沒有強連通分量大啊。

借這道題來紀念一下強連通分量,希望以後有用上的時候。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
const int maxn=105,maxm=505,inf=0x3f3f3f3f;
int n,m,dp[maxn][maxm];
int cost[maxn],val[maxn],tmp_w[maxn],tmp_v[maxn];
int scc_num[maxn],scc_cnt,deg[maxn];
int dfn[maxn],low[maxn],dfs_clock;
struct qxx{
	int Begin[maxn],Next[maxn],to[maxn],e;
	void init(){
		memset(Begin,0,sizeof(Begin)),e=0;
	}
	void add(int u,int v){
		to[++e]=v,Next[e]=Begin[u],Begin[u]=e;
	}
}E,G;
stack<int>S;
void dfs(int u){
	S.push(u);
	low[u]=dfn[u]=++dfs_clock;
	for(int i=E.Begin[u];i;i=E.Next[i]){
		int v=E.to[i];
		if(!dfn[v]){
			dfs(v);
			low[u]=min(low[u],low[v]);
		}else if(!scc_num[v])
			low[u]=min(low[u],low[v]);
	}if(low[u]==dfn[u]){
		scc_num[u]=++scc_cnt;
		cost[scc_cnt]=tmp_w[u];
		val[scc_cnt]=tmp_v[u];
		while(S.top()!=u){
			cost[scc_cnt]+=tmp_w[S.top()];
			val[scc_cnt]+=tmp_v[S.top()];
			scc_num[S.top()]=scc_cnt,S.pop();
		}S.pop();
	}
}
bool vis[maxn];
void dfs_dp(int u){
	vis[u]=1;
	for(int j=0;j<cost[u];j++)dp[u][j]=-inf;
	for(int j=cost[u];j<=m;j++)dp[u][j]=val[u];
	for(int i=G.Begin[u];i;i=G.Next[i]){
		int v=G.to[i];
		if(vis[v])continue;
		dfs_dp(v);
		for(int j=m;j>=cost[u];j--)
			for(int k=j-cost[u];k>=cost[v];k--)
				dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
	}
}
int main(){
	int k;
	scanf("%d%d",&n,&m);
	E.init(),G.init();
	for(int i=1;i<=n;i++)
		scanf("%d",&tmp_w[i]);
	for(int i=1;i<=n;i++)
		scanf("%d",&tmp_v[i]);
	for(int i=1;i<=n;i++){
		scanf("%d",&k);
		if(k)E.add(k,i);
	}
	for(int i=1;i<=n;i++)
		if(!dfn[i])
			dfs(i);
	for(int i=1;i<=n;i++)
		for(int j=E.Begin[i];j;j=E.Next[j])
			if(scc_num[i]!=scc_num[E.to[j]]){
				G.add(scc_num[i],scc_num[E.to[j]]);
				deg[scc_num[E.to[j]]]++;
			}
	for(int i=1;i<=scc_cnt;i++)
		if(!deg[i])
			G.add(scc_cnt+1,i);
	dfs_dp(scc_cnt+1);
	printf("%d\n",max(0,dp[scc_cnt+1][m]));
	return 0;
}

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