【BZOJ1179】【Apio2009】Atm 强连通分量缩点+拓扑DP/拓扑最长路 kosaraju+tarjan+dfs转非递归三种代码

原创 2015年01月10日 14:43:07

题解:

首先第一个阶段,

可以写kosaraju、也可以写tarjan。

这两种还都分递归和dfs转非递归。

----------------------------------四种方案。

第二个阶段,可以写拓扑DP

也可以写最长路

----------------------------------乘上之前的,,八种方案。


本文写了kosaraju递归版,tarjan递归版,kosaraju非递归版。

……只怪学校oj系统栈太小。。都是逼得啊。


代码1(tarjan):

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 501000
using namespace std;
struct KSD
{
	int u,v,next;
}e[N],E[N];
int head[N],cnt,Head[N];

void add(int u,int v)
{
	cnt++;
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].next=head[u];
	head[u]=cnt;
}
void Add(int u,int v)
{
	cnt++;
	E[cnt].v=v;
	E[cnt].next=Head[u];
	Head[u]=cnt;
}

int dfn[N],low[N];
int group,id[N];
bool in[N];

int stk[N],top;
int fee[N],Fee[N];
bool Bar[N],bar[N];
void tarjan(int x)
{
	dfn[x]=low[x]=++cnt;
	stk[++top]=x,in[x]=1;
	for(int i=head[x];i;i=e[i].next)
	{
		if(!dfn[e[i].v])
		{
			tarjan(e[i].v);
			low[x]=min(low[x],low[e[i].v]);
		}
		else if(in[e[i].v])low[x]=min(low[x],dfn[e[i].v]);
	}
	if(low[x]==dfn[x])
	{
		group++;
		do{
			in[stk[top]]=0,id[stk[top]]=group;
			Fee[group]+=fee[stk[top]];
			Bar[group]|=bar[stk[top]];
		}while(stk[top--]!=x);
	}
}
int n,m,s,p;
bool ok[N];
void bfs()
{
	int i,u,v;
	stk[top=1]=s;
	while(top)
	{
		u=stk[top--];
		ok[u]=1;
		for(i=head[u];i;i=e[i].next)
		{
			v=e[i].v;
			if(!ok[v])stk[++top]=v;
		}
	}
}
int dp[N],d[N];
int main()
{
//	freopen("test.in","r",stdin);
	int i,j,k;
	int a,b,c;
	int u,v;
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++)scanf("%d%d",&a,&b),add(a,b);
	for(i=1;i<=n;i++)scanf("%d",&fee[i]);
	scanf("%d%d",&s,&p);
	for(i=1;i<=p;i++)scanf("%d",&c),bar[c]=true;

	for(c=cnt,cnt=0,i=1;i<=n;i++)if(!dfn[i])tarjan(i);
	bfs();
	for(cnt=0,i=1;i<=c;i++)
	{
		if((!ok[e[i].u])||(!ok[e[i].v]))continue;
		a=id[e[i].u],b=id[e[i].v];
		if(a==b)continue;
		Add(a,b);
		d[b]++;
	}

	stk[top=1]=id[s];
	int ans=0;
	while(top)
	{
		u=stk[top--];
		if(Bar[u])ans=max(ans,dp[u]+Fee[u]);
		for(i=Head[u];i;i=E[i].next)
		{
			v=E[i].v;
			dp[v]=max(dp[v],dp[u]+Fee[u]);
			d[v]--;
			if(!d[v])stk[++top]=v;
		}
	}
	printf("%d\n",ans);
	return 0;
}


代码2(kosaraju):

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 501000
using namespace std;
struct KSD
{
	int u,v,next;
}e[N],ez[N];
int head[N],lux[N],cnt;
inline void add(int u,int v)
{
	cnt++;
	ez[cnt].v=e[cnt].u=u;
	e[cnt].v=v;
	ez[cnt].next=lux[v];
	e[cnt].next=head[u];
	head[u]=lux[v]=cnt;
}
inline void add2(int u,int v)
{
	cnt++;
	ez[cnt].v=v;
	ez[cnt].next=lux[u];
	lux[u]=cnt;
}

bool vis[N];
int dfn[N],top;
int id[N],group;

int n,m,s,p;
int fee[N];
bool bar[N];

int Fee[N];
bool Bar[N];

void dfs1(int x)
{
	vis[x]=1;
	for(int i=head[x];i;i=e[i].next)if(!vis[e[i].v])dfs1(e[i].v);
	dfn[++top]=x;
}
void dfs2(int x)
{
	id[x]=group;
	Bar[group]|=bar[x];
	Fee[group]+=fee[x];
	for(int i=lux[x];i;i=ez[i].next)if(!id[ez[i].v])dfs2(ez[i].v);
}
int d[N],dp[N];
bool ok[N];
void bfs()
{
	int i,u,v;
	dfn[top=1]=s;
	while(top)
	{
		u=dfn[top--];
		ok[u]=1;
		for(i=head[u];i;i=e[i].next)
		{
			v=e[i].v;
			if(!ok[v])dfn[++top]=v;
		}
	}
}
int main()
{
//	freopen("test.in","r",stdin);
	int i,j,k;
	int a,b,c;
	scanf("%d%d",&n,&m);
	while(m--)scanf("%d%d",&a,&b),add(a,b);
	for(i=1;i<=n;i++)scanf("%d",&fee[i]);
	scanf("%d%d",&s,&p);
	while(p--)scanf("%d",&c),bar[c]=true;

	bfs();
	for(i=1;i<=n;i++)if(!vis[i])dfs1(i);
	for(i=top;i;i--)if(!id[dfn[i]])group++,dfs2(dfn[i]);
	memset(lux,0,sizeof(lux));
	c=cnt,cnt=0;

	for(i=1;i<=c;i++)
	{
		if(!ok[e[i].u])continue;
		a=id[e[i].u],b=id[e[i].v];
		if(a==b)continue;
		add2(a,b);
		d[b]++;
	}
	dfn[top=1]=id[s];
	int ans=0;
	while(top)
	{
		a=dfn[top--];
		if(Bar[a])ans=max(ans,dp[a]+Fee[a]);
		for(i=lux[a];i;i=ez[i].next)
		{
			c=ez[i].v;
			dp[c]=max(dp[c],dp[a]+Fee[a]),d[c]--;
			if(!d[c])dfn[++top]=c;
		}
	}
	printf("%d\n",ans);
	return 0;
}


代码3(kosaraju+主要部分转非递归):

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 501000
using namespace std;
struct KSD
{
	int u,v,next;
}e[N],ez[N];
int head[N],lux[N],cnt;
inline void add(int u,int v)
{
	cnt++;
	ez[cnt].v=e[cnt].u=u;
	e[cnt].v=v;
	ez[cnt].next=lux[v];
	e[cnt].next=head[u];
	head[u]=lux[v]=cnt;
}
inline void add2(int u,int v)
{
	cnt++;
	ez[cnt].v=v;
	ez[cnt].next=lux[u];
	lux[u]=cnt;
}
 
bool vis[N];
int dfn[N],top;
int id[N],group;
 
int n,m,s,p;
int fee[N];
bool bar[N];
 
int Fee[N];
bool Bar[N];

int stk[N];
int which[N];
inline void dfs1(int x)
{
	int i,u,v;
	vis[x]=1;
	which[x]=head[x];
	stk[top=1]=x;
	while(top)
	{
		u=stk[top];
		i=which[u];
		if(!i)
		{
			top--;
			dfn[++cnt]=u;
			continue;
		}
		if(!vis[v=e[i].v])
		{
			vis[v]=1;
			which[v]=head[v];
			stk[++top]=v;
		}
		which[u]=e[i].next;
	}
}/*   ***************************************这个注释部分的dfs转非递归写挂了
inline void dfs2(int x)
{
	int i,u,v;
	stk[top=1]=x;
	group++;
	while(top)
	{
		u=stk[top--];
		id[u]=group;
		Bar[group]|=bar[u];
		Fee[group]+=fee[u];
		for(i=lux[u];i;i=ez[i].next)
			if(!id[v=ez[i].v])
				stk[++top]=v;
	}
}*/
void dfs2(int x)
{
	id[x]=group;
	Bar[group]|=bar[x];
	Fee[group]+=fee[x];
	for(int i=lux[x];i;i=ez[i].next)if(!id[ez[i].v])dfs2(ez[i].v);
}
int d[N],dp[N];
bool ok[N];
void bfs()
{
	int i,u,v;
	dfn[top=1]=s;
	while(top)
	{
		u=dfn[top--];
		ok[u]=1;
		for(i=head[u];i;i=e[i].next)
		{
			v=e[i].v;
			if(!ok[v])dfn[++top]=v;
		}
	}
}
int main()
{
//	freopen("test.in","r",stdin);
	int i,j,k;
	int a,b,c;
	scanf("%d%d",&n,&m);
	while(m--)scanf("%d%d",&a,&b),add(a,b);
	for(i=1;i<=n;i++)scanf("%d",&fee[i]);
	scanf("%d%d",&s,&p);
	while(p--)scanf("%d",&c),bar[c]=true;
	c=cnt,cnt=0;

	bfs();
	for(cnt=0,i=1;i<=n;i++)if(!vis[i])dfs1(i);
	for(cnt=0,i=n;i;i--)if(!id[dfn[i]])group++,dfs2(dfn[i]);
	memset(lux,0,sizeof(lux));
 
	for(cnt=0,i=1;i<=c;i++)
	{
		if(!ok[e[i].u])continue;
		a=id[e[i].u],b=id[e[i].v];
		if(a==b)continue;
		add2(a,b);
		d[b]++;
	}
	dfn[top=1]=id[s];
	int ans=0;
	while(top)
	{
		a=dfn[top--];
		if(Bar[a])ans=max(ans,dp[a]+Fee[a]);
		for(i=lux[a];i;i=ez[i].next)
		{
			c=ez[i].v;
			dp[c]=max(dp[c],dp[a]+Fee[a]),d[c]--;
			if(!d[c])dfn[++top]=c;
		}
	}
	printf("%d\n",ans);
	return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

拓扑图+ dp

题目: J: Meeting Time 时间限制: 1 Sec  内存限制: 64 MB 提交: 10  解决: 5 [提交][状态][讨论版] 题目描述 Bessie and her s...

【bzoj2956】模积和 数论分块

额,终于把图片搞出来了。 这个式子处理起来是O(n)的,但是我们发现n/i只用O(√n)个取值,我们枚举这O(√n)个取值。 假如枚举的取值为k,则把所有n/i=k的i求和即可 (k+1)*i>...

Bzoj2561:最小生成树:网络流,最小割

题目链接:最小生成树 发现如果这条边可能出现在最大生成树上的话,那么可以代替这条边的所有边都不连通,换句话说这条边是连接u,v必不可少的 于是我们把所有权值大于L的边建成一张边权去为1的图对U,V跑最...

【BZOJ】1179 [Apio2009]Atm 强连通分量+最短路

题目传送门 这题的正解——强连通分量+最短路,还是需要一定的想象力的。 首先,我们把所有能够互相到达的点(也就是强连通分量)进行缩点,缩完后的点的权值就是原先所有点的权值和。 然后,我们对缩完点...
  • lyfsb
  • lyfsb
  • 2017年04月20日 20:11
  • 212

[APIO2009]抢掠计划(强连通分量+缩点+拓扑排序+dp)

题意: 给定一个有向图,从指定起点出发,到任意一个指定终点停止,求经过的所有结点的最大点权和。点数、边数 因为一个强连通分量内的点相互可达,所以如果要经过其中一个点,就应经过它所在的强连通...
  • cjk_cjk
  • cjk_cjk
  • 2015年05月03日 23:30
  • 409

[BZOJ1179][APIO2009][Tarjan][拓扑排序][递推]Atm

[Problem Description] [Algorithm] 非递归Tarjan,拓扑排序,递推 [Analysis] 首先用强连通分量对图进行缩点。很明显只要能到强连通分量...

【BZOJ1179】[Apio2009]Atm【SCC】【最长路】

【题目链接】 tarjan先缩点,然后跑个最长路。读入一个酒吧位置就更新一次答案。 /* Pigonometry */ #include #include #include #include...

【BZOJ】【APIO2009】【ATM】【强连通分量+DP】

传送门: http://www.lydsy.com/JudgeOnline/problem.php?id=1179 Tarjan缩点+DAG

[BZOJ1179]APIO2009 ATM |强联通分量|DP

这题和1093差不多,也就是缩环之后spfa/拓扑排序/记忆化搜索搞一下,多注意一点的就是一个点有酒吧的时候它才能向前更新答案。。 #include #include #include #defin...

bzoj1179 [Apio2009]Atm[tarjan缩点]

Description Siruseri城中的道路都是单向的。不同的道路由路口连接。按照法律的规定,在每个路口都设立了一个Siruseri银行的ATM取款机。令人奇怪的是,Siruseri的酒吧也...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【BZOJ1179】【Apio2009】Atm 强连通分量缩点+拓扑DP/拓扑最长路 kosaraju+tarjan+dfs转非递归三种代码
举报原因:
原因补充:

(最多只允许输入30个字)