P3387 【模板】缩点

      ~~~~~      P3387 【模板】缩点       ~~~~~      总题单链接

缩点即相关定义

      ~~~~~      强连通分量:原图一个极大子图使得从这个子图中的任意一个点出发都可以到达这个子图的任意一个点。

      ~~~~~      而缩点,就是找强连通分量的过程。

为什么要缩点

      ~~~~~      将有环图变为无环图,然后就可以用一些在环上比较难用的东西,比如 D P DP DP

怎么找到每个点对应的强连通分量

      ~~~~~       d f s dfs dfs序 访问图上的每个点,每个点只访问一遍,每个点第一次访问的时候加入到栈里。

      ~~~~~      先来看看时间戳的定义,若一个点的时间戳为 x x x,那它就是在 d f s dfs dfs 时第 x x x 个被访问到的点。

      ~~~~~      对于图上的每个点,记录 d f n [ i ] dfn[i] dfn[i] 表示 点 i i i 的时间戳, l o w [ i ] low[i] low[i] 表示 点 i i i 在不走进入点 i i i 的点的情况下能走到的最早时间戳。举个栗子,在 d f s dfs dfs 的时候是从 u u u 走到 v v v 的,那 l o w [ v ] low[v] low[v] 就是 v v v 在不仅过过 u u u 的情况下能走到的最早时间戳。

      ~~~~~      若在离开点 u u u 时, l o w [ v ] = d f n [ u ] low[v]=dfn[u] low[v]=dfn[u] 则当前还在栈内的点就是一个强连通分量。为什么?因为 l o w [ v ] = d f n [ u ] low[v]=dfn[u] low[v]=dfn[u] 说明从当前栈内点出发在不经过 u u u 的情况下到不了比 u u u 时间戳更小的点,所以这些点是一个强连通分量。对这句话理解有问题的同学可以再看一看强连通分量的定义。

怎么缩点

      ~~~~~      遍历每条边,如果这条边的两个端点在两个强连通分量,就把这两个强连通分量连边。这样可能会有重边,可以在连边前判断一下。

模板题代码

      ~~~~~      缩点值后就用 d p dp dp 来统计答案。

#include<bits/stdc++.h>
#define ll long long
using namespace std;

ll dfn[10005],low[10005];
ll pos[10005],siz[10005];
ll stk[10005],init[10005];
vector<ll>eg[10005],ng[10005];
ll n,m,a[10005],top,tot,cnt,dp[1005];

void Tarjan(ll p){
	init[p]=1;
	stk[++top]=p;
	dfn[p]=low[p]=++tot;
	for(ll v:eg[p]){
		if(!dfn[v]){
			Tarjan(v);
			low[p]=min(low[p],low[v]);
		}
		else if(init[v])low[p]=min(low[p],dfn[v]);
	}
	if(low[p]==dfn[p]){
		cnt++;
		while(top){
			ll v=stk[top--];
			init[v]=0;
			pos[v]=cnt;
			siz[cnt]+=a[v];
			if(v==p)break;
		}
	}
}

signed main(){
	ios::sync_with_stdio(false);
	
	cin>>n>>m;
	for(ll i=1;i<=n;i++)cin>>a[i];
	while(m--){
		ll x,y;cin>>x>>y;
		eg[x].push_back(y);
	}
	
	for(ll i=1;i<=n;i++)
		if(!dfn[i])Tarjan(i);
		
	for(ll u=1;u<=n;u++)
		for(ll v:eg[u])
			if(pos[u]!=pos[v])
				ng[pos[u]].push_back(pos[v]);
		
	ll ans=0;
	for(ll i=cnt;i>=1;i--){
		dp[i]+=siz[i];
		ans=max(ans,dp[i]);
		for(ll v:ng[i])
			dp[v]=max(dp[v],dp[i]);
	}
	cout<<ans<<endl;
	
	return 0;
}
  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Vue 中实现一个可以收缩的 group box,可以使用组件化的思路,将 group box 封装为一个组件,并添加一个按钮来控制其展开/收缩状态。 以下是一个简单的实现示例: ``` <template> <div class="group-box"> <div class="header" @click="toggle"> {{ title }} <span class="icon" :class="{ 'icon-expanded': expanded, 'icon-collapsed': !expanded }"></span> </div> <div class="content" v-show="expanded"> <slot></slot> </div> </div> </template> <script> export default { props: { title: { type: String, required: true, }, }, data() { return { expanded: true, }; }, methods: { toggle() { this.expanded = !this.expanded; }, }, }; </script> <style> .group-box { border: 1px solid #ccc; border-radius: 4px; margin-bottom: 16px; } .header { background-color: #f0f0f0; padding: 8px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; } .icon { width: 12px; height: 12px; border-top: 2px solid currentColor; border-right: 2px solid currentColor; transform: rotate(45deg); } .icon-collapsed { transform: rotate(-135deg); } .content { padding: 8px; } </style> ``` 使用方式: ``` <template> <div> <group-box title="Group Box"> <p>Some content</p> </group-box> </div> </template> <script> import GroupBox from './GroupBox.vue'; export default { components: { GroupBox, }, }; </script> ``` 在上面的示例中,我们创建了一个 `GroupBox` 组件,它接受一个 `title` 属性作为组标题,并使用一个 `expanded` 数据属性来控制组展开/收缩状态。`toggle` 方法用来切换组状态。在组件模板中,我们使用了 `v-show` 指令来根据 `expanded` 属性来控制组展示状态,同时添加了一个按钮来触发 `toggle` 方法。 最后,我们可以在父组件中使用 `GroupBox` 组件,传递标题和内容作为插槽内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值