2021.8.9提高B组模拟1T2 QYQ在艾泽拉斯(Tarjan强连通分量)(并查集)

Posted SSL_LKJ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021.8.9提高B组模拟1T2 QYQ在艾泽拉斯(Tarjan强连通分量)(并查集)相关的知识,希望对你有一定的参考价值。

QYQ在艾泽拉斯

题目大意

输入样例

3 2
1 2
3 1
1 2 1
0

输出样例

4
样例说明:
QYQ从3号点开始,走到2号点,最后走到1号点,结束旅程,共获得1+2+1=4价值的宝物

题目数据

解题思路

先用Tarjan强连通分量缩点

再用并查集求出每个岛屿最大的价值

我太蒟了,以至于不会敲这题的 dfs ,改了太久都没 AC ,只能用并查集,望各位大佬见谅

AC代码

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int n,m,k,T,TT,tot,tot1,top,answer; 
int f[100005],fa[100005],ru[100005],ans[100005],dfn[100005],low[100005],col[100005],sum[100005],num[100005],stak[100005],head[100005],head1[100005];
struct node

	int to,next;
a[2000005],b[2000005];
void add(int x,int y)

	a[++tot]=(node)y,head[x];
	head[x]=tot;

void add1(int x,int y)

	b[++tot1]=(node)y,head1[x];
	head1[x]=tot1;

void Tarjan(int x)//模板

	dfn[x]=low[x]=++T;
	stak[++top]=x;
	for(int i=head[x];i;i=a[i].next)
	
		int v=a[i].to;
		if(!dfn[v])
		
			Tarjan(v);
			low[x]=min(low[x],low[v]);
		
		else if(!col[v])low[x]=min(low[x],low[v]);
	
	if(dfn[x]==low[x])
	
		col[x]=++TT;
		sum[TT]+=num[x];
		while(stak[top]!=x)sum[TT]+=num[stak[top]],col[stak[top--]]=TT;
		top--;
	
	return;

int getfather(int x)

	if(fa[x]==x)return x;
	return fa[x]=getfather(fa[x]);

void work(int x)

	f[x]+=sum[x];
	for(int i=head1[x];i;i=b[i].next)
	
		getfather(x),getfather(b[i].to);
		fa[fa[x]]=fa[b[i].to];
		ru[b[i].to]--;
		f[b[i].to]=max(f[x],f[b[i].to]);
		if(!ru[b[i].to])work(b[i].to);
	

bool cmp(int x,int y)

	return x>y;

int main()

	freopen("azeroth.in","r",stdin);
	freopen("azeroth.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
	
	for(int i=1;i<=n;i++)
		 scanf("%d",&num[i]);
	scanf("%d",&k);
	for(int i=1;i<=n;i++)
		 if(!dfn[i])Tarjan(i);
	for(int i=1;i<=n;i++)//建新图
	 	for(int j=head[i];j;j=a[j].next)
	 	
	 		int v=a[j].to;
	 		if(col[i]!=col[v])
		 	
	 			add1(col[i],col[v]);
		 		ru[col[v]]++;
			
		 
	for(int i=1;i<=TT;i++)fa[i]=i;//初值
	for(int i=1;i<=TT;i++)if(!ru[i])work(i);//并查集
	for(int i=1;i<=TT;i++)getfather(i),ans[fa[i]]=max(ans[fa[i]],f[i]);//ans为各个岛屿最大价值
	sort(ans+1,ans+n+1,cmp);//排序
	for(int i=1;i<=min(n,k+1);i++)//求答案
		answer+=ans[i];
	printf("%d",answer);
	return 0;


谢谢

以上是关于2021.8.9提高B组模拟1T2 QYQ在艾泽拉斯(Tarjan强连通分量)(并查集)的主要内容,如果未能解决你的问题,请参考以下文章

2021.7.12提高B组模拟1T2 最短路径(DP)

2021.8.9提高B组模拟1T3 平均数(二分)(贪心)

2021.8.9提高B组模拟1T1 最长公共回文子序列(dfs)

2021.8.9提高B组模拟1T4 着色(组合数学)

2021.8.9提高B组模拟1T4 着色(组合数学)

2021.8.9提高B组模拟1T3 平均数(二分)(贪心)