首页 > 其他分享 >Tarjan问题

Tarjan问题

时间:2022-09-24 08:33:28浏览次数:53  
标签:pre Tarjan group min int 问题 maxn low

强连通

学习资料

强连通,又名\(scc\),即有向图中可以相互到达的子图,如 \(\quad\) 3->4;4->3 3与4即一对\(scc\);
\(Tarjan\)的作用可以将有环图转为有向无环图
既然是有向无环图 拓扑序的优势就体现出来了
更新树中的节点就可以通过拓扑排序进行

最优贸易

题意分析

在一个有向有环图中,求出从\(1\)开始的到达\(n\)的所有路径中,最大的点权差

这时候的数据结构狂魔就拿出了\(Tarjan\),重新建图为\(DAG\),用\(BFS\)拓扑\(dp\)一下
就\(A\)了这题

点击查看代码
#include<bits/stdc++.h>
#define maxn 100010
#define N 500010
#define int long long
using namespace std;
int head[N],nex[N],ver[N],tot;
int dfs[maxn],low[maxn],vis[maxn],dp[maxn],Gro[maxn],st[maxn];
int cnt,top,group,MaxG[maxn],MinG[maxn],in[maxn];
int n,m,val[maxn];
void add(int u,int v)
{
	ver[++tot]=v; nex[tot]=head[u];head[u]=tot;
}

int head2[N],nex2[N],ver2[N],tot2,pre_min[N];
void add2(int u,int v)
{
	ver2[++tot2]=v;  nex2[tot2]=head2[u];  head2[u]=tot2;
}

void tarjan(int x)
{
	dfs[x]=low[x]=++cnt;
	st[++top]=x; vis[x]=1;
	for(int i=head[x];i;i=nex[i])
	{
		int v=ver[i];
		if(!dfs[v])
		{;
			tarjan(v);
			low[x]=min(low[x],low[v]);
		}
		else
		if(vis[v])
		{
			low[x]=min(low[x],dfs[v]);
		}
	}
	if(dfs[x]==low[x])
	{
		int y; group++;
		do
		{
			y=st[top]; top--;
			Gro[y]=group; vis[y]=0;
			
			MaxG[group]=max(MaxG[group],val[y]);
			MinG[group]=min(MinG[group],val[y]);
			
		}while(x!=y);
	}
}
queue<int> q;
void BFS(int x)
{
	pre_min[x]=min(pre_min[x],MinG[x]);
	dp[x]=max(dp[x],MaxG[x]-pre_min[x]);
	while(!q.empty())
	{
		int x=q.front(); q.pop();
		for(int i=head2[x];i;i=nex2[i])
		{
			int v=ver2[i];
			in[v]--;
			pre_min[v]=min(pre_min[x],MinG[v]);
			dp[v]=max(dp[x],max(dp[v],MaxG[v]-pre_min[v]));
			if(!in[v])
			{
				q.push(v);
			}
		}
	}
}

signed main()
{
	scanf("%lld%lld",&n,&m);
	
	for(int i=1;i<=n;i++) scanf("%lld",&val[i]);
	
	for(int i=1,u,v,c;i<=m;i++)
	{
		scanf("%lld%lld%lld",&u,&v,&c);
		if(c==1) add(u,v);
		if(c==2) add(u,v),add(v,u);
	}
	
	memset(MinG,100,sizeof MinG);
	for(int i=1;i<=n;i++) if(!dfs[i]) tarjan(i);

	
//	for(int i=1;i<=n;i++) cout<<Gro[i]<<" ";
	
	for(int i=1;i<=n;i++)
	{
		for(int j=head[i];j;j=nex[j])
		{
			
			int v=ver[j];
			if(Gro[v]!=Gro[i]) 
			{
//				cout<<i<<" = "<<Gro[i]<<"----"<<v<<" = "<<Gro[v]<<endl;
				add2(Gro[i],Gro[v]);
				in[Gro[v]]++;
			}
		}
	}
	for(int i=1;i<=group;i++) 
	{
//		cout<<i<<" "<<in[i]<<endl;;
		if(!in[i])
		{
//			cout<<"!!  "<<i<<endl;
			q.push(i);
		}
	}
	
 	memset(pre_min,127,sizeof pre_min);
	BFS(Gro[1]);
	cout<<dp[Gro[n]];
	return 0;
}
/*

5 5
4 3 5 6 1 
1 2 1 
1 4 1 
2 3 2 
3 5 1
4 5 2 

12 14
100 10 11 10 10 1 1 1 1 1 1 1
1 4 1
4 5 2
1 2 1
2 3 2
5 6 1
6 7 2
7 12 1
3 8 1
2 5 1
8 9 2
3 10 1
10 11 2
11 12 1
9 12 1

*/

但是 这题其实仅用简简单单的\(DFS\)就可以解决\(\quad\) 再次感谢巨佬@HY喵的出其不意的思路
在每次\(DFS\)时,用一个\(Flag\)判断是否可以更新

点击查看代码
void dfs(int x,int minx,int pre) //x表示当前访问的节点编号,minx表示目前为止的最小的商品价格,pre表示上一个节点的编号
{                       
    int flag=1;                                          //用于判断是否已被访问过,需要终止
    minx=min(c[x],minx);                                 //判断本次的商品价格是否是最小值
    if (mi[x]>minx) mi[x]=minx,flag=0;                   //判断mi数组(记录了每次的最小值)并更新,在更新的同时把flag设为0(不用退出了)
    做动态规划;                                         //别着急flag还会继续更新的
    if (flag) return;                                    //退出,千万不能露,不然程序就会放飞自我,堆栈溢出->完美MLE只有10分。
    for (int i=0;i<g[x].size();i++) dfs(g[x][i],minx,x); //继续进行递归调用,访问目前节点能访问到的节点。
}

标签:pre,Tarjan,group,min,int,问题,maxn,low
From: https://www.cnblogs.com/llwwll/p/16724886.html

相关文章

  • Mac系统睡眠掉电问题
    查看Mac休眠模式打开启动台→其他→终端;复制命令:pmset-g,在终端窗口粘贴后回车,如果提示输入「password」,直接输入自己的开机密码,密码是不会显示出来的,直接输入就行,输完......
  • Vue2项目解决-js/css文件无法引用问题
    打包:    在vue.config.js文件中  const{defineConfig}=require('@vue/cli-service')module.exports=defineConfig({  transpileDependencies:t......
  • SAP 电商云 Spartacus UI userID 即邮件地址中的加号问题
    如果用户登录名或密码包含符号+,它将被替换为空格,因为Content-Type等于application/x-www-form-urlencoded。下面是一个例子:https://:9002/occ/v2/electronics-spa/f......
  • 【问题记录】Ant Design的Select标签检验不通过不生成tag
    问题:tags模式下如何检验输入数据,如果检验不通过不生成tag解决办法:在onChange事件中检验即可。tags模式<Selectmode="tags"placeholder="Pleaseselect"......
  • Delphi 11.2的一个问题
    https://quality.embarcadero.com/browse/RSP-39499functionTAndroidVirtualKeyboard.DefineNativeView(constAObject:TFmxObject):JView;functionIsNativeCon......
  • 盘点一个Python网络爬虫实战问题
    大家好,我是皮皮。一、前言前几天在Python铂金交流群【红色基因代代传】问了一个Python网络爬虫的问题,提问截图如下:代码截图如下:报错截图如下:要么就是原始网页没那......
  • idea中包已经导入,但是运行还是提示找不到包问题
    1.在idea的命令行中输入命令执行使用mvnidea:ideaj进行重构,这个作用就是:maven依赖更新不完整命令,强制刷新idea缓存。2.在项目右键,找到maven-->reimport,或者在项目右......
  • pycharm打字卡顿问题解决
    问题描述:我在pycharm中使用的远程服务器中的环境,工程也是本机映射到远程环境中,在某次断网以后,再次使用就变得非常卡,具体现象就是我码字要等,整个pycharm就无法点击,过了5秒以......
  • 二分查找步骤及问题总结
    二分查找参数:有序数组arr(这里按升序来讲),待搜索的值target步骤定义左边界left和有边界right获取中间索引(整数)mid=(left+right)/2,注意:js只有小数,mid需要再取整......
  • memset函数的赋值问题
    memset函数的赋值问题memset函数的定义在C++标准库中对memset函数的定义为:定义于头文件cstring。转换值ch为unsignedchar并复制它到dest所指向对象的首count......