首页 > 其他分享 >[题解]P3119 [USACO15JAN] Grass Cownoisseur G

[题解]P3119 [USACO15JAN] Grass Cownoisseur G

时间:2024-11-13 18:18:45浏览次数:1  
标签:int 题解 节点 dfn low Grass stack Cownoisseur

P3119 [USACO15JAN] Grass Cownoisseur G

显然我们可以先跑强连通分量,由\(x\)个点缩成的新点\(u\)权值为\(v[u]=x\)。

下文中的节点\(1\)均表示缩点后节点\(1\)所在的节点。

我们在缩点后的DAG上跑拓扑排序,预处理出\(fa[i]\)和\(fb[i]\),分别表示“\(1\)到\(i\)路径的点权和”,“\(i\)到\(1\)路径的点权和”,后者可以建反图求解。

我们应该找到节点\(u,v\)使得:

  • \(1\)可以到达\(u\)
  • \(u\)到\(v\)有边
  • \(v\)可以到达\(v\)

这样一个合法的路径(\(1\)到\(u\),\(u\)逆行到\(v\),\(v\)到\(i\))就产生了,用\(fa[u]+fb[v]-v[1]\)更新答案即可。

注意,如果整个图是一个强连通分量,缩点后会只剩\(1\)个点,需要提前用\(v[1]\)更新答案,否则无法通过Subtask #1。

时间复杂度\(O(n+m)\)。

点击查看代码
#include<bits/stdc++.h>
#define N 100010
using namespace std;
int n,m,dfn[N],low[N],tim,st[N],top,ans;
int v[N],ori[N],dega[N],degb[N],fa[N],fb[N];
bitset<N> in_stack;
vector<int> G[N],Ga[N],Gb[N];
queue<int> q;
void tarjan(int u){
	dfn[u]=low[u]=++tim;
	st[++top]=u,in_stack[u]=1;
	for(int i:G[u])
		if(!dfn[i])
			tarjan(i),
			low[u]=min(low[u],low[i]);
		else if(in_stack[i])
			low[u]=min(low[u],dfn[i]);
	if(dfn[u]==low[u]){
		while(1){
			int t=st[top--];
			in_stack[t]=0,ori[t]=u,v[u]++;
			if(t==u) break;
		}
	}
}
void topo(vector<int> G[],int deg[],int f[N],int s){
	for(int i=1;i<=n;i++) if(!deg[i]) q.push(i);
	memset(f,0,sizeof(int));
	while(!q.empty()){
		int u=q.front();
		q.pop();
		if(u==s||f[u]) f[u]+=v[u];
		for(int i:G[u]){
			f[i]=max(f[i],f[u]);
			deg[i]--;
			if(!deg[i]) q.push(i);
		}
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr),cout.tie(nullptr);
	cin>>n>>m;
	for(int i=1,u,v;i<=m;i++){
		cin>>u>>v;
		G[u].emplace_back(v);
	}
	for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
	ans=v[ori[1]];
	for(int i=1;i<=n;i++){
		for(int j:G[i]){
			if(ori[i]!=ori[j]){
				Ga[ori[i]].emplace_back(ori[j]);
				Gb[ori[j]].emplace_back(ori[i]);
				dega[ori[j]]++,degb[ori[i]]++;
			}
		}
	}
	topo(Ga,dega,fa,ori[1]);
	topo(Gb,degb,fb,ori[1]);
	for(int i=1;i<=n;i++){
		if(!fb[i]) continue;
		for(int j:Ga[i]){
			if(!fa[j]) continue;
			ans=max(ans,fb[i]+fa[j]-v[ori[1]]);
		}
	}
	cout<<ans<<"\n";
	return 0;
}

标签:int,题解,节点,dfn,low,Grass,stack,Cownoisseur
From: https://www.cnblogs.com/Sinktank/p/18544498

相关文章

  • 洛谷P11228的C++题解
    题目分析题目题目让我们算出机器人走步后经过了多少个不重复的点这道题不是搜索!直接按照题意模拟就行了。遇到墙就向右转,不是就直行。特别注意:向右转也是一步!一个格子最多算一遍!我们可以用一个标记数组 st,走过的点就打上标记。判断走道的点有没有打上标记,有就不......
  • P2779 [AHOI2016初中组] 黑白序列题解
    题意:小可可准备了一个未完成的黑白序列,用B和W表示黑色和白色,用?表示尚未确定。他希望知道一共有多少种不同的方法,在决定了每一个?位置的颜色后可以得到一个小雪喜欢的黑白序列。其中,小雪喜欢的黑白序列指的是对于任何正整数\(n\),由连续\(n\)个黑接上连续\(n\)个白......
  • 题解:CF2025E Card Game
    在这貌似和大部分做法不太一样(?)权当卡特兰数的复习题吧。不会卡特兰数的可以先看文末。如果没有花色\(1\)这道题就很简单了,对于每个别的花色都有\(C(m)\)种分配方案。\(C(n)\)表示卡特兰数的第\(n\)项,答案就是乘起来。发现除了花色\(1\)每种花色的牌都是独立的。这......
  • P6628 [省选联考 2020 B 卷] 丁香之路 题解
    P6628[省选联考2020B卷]丁香之路题解首先考虑题目中路径权值的含义:\(i,j\)两点之间的最短路就是\(|i-j|\)直接连边。题目要求从\(s\)遍历到每个点,到终点每个\(x\)的最短时间。于是我们不妨枚举每个\(x\),考虑在\(O(n)\)至\(O(n\logn)\)的时间复杂度里解决问题......
  • 《统计每个月兔子的总数》 递归、记忆化数组、动态规划题解
    目录题目描述输入描述输出描述解析完整代码描述有一对兔子,从出生后第3个月起每个月都生一对兔子,一对小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第n个月(n<=50)的兔子总数为多少对?输入描述输入1个整数n,表示第几个月输出描述第n个月兔子的总数量有多少?......
  • P10833 [COTS 2023] 下 Niz题解
    题意:给定长度为\(N\)的序列\(a\),求满足以下条件的\((l,r)\)对数:\(1\lel\ler\leN\);\(a_l,a_{l+1},\cdots,a_{r-1},a_r\)是\(1\simr-l+1\)的排列。\(1\leN\le10^6\);\(1\lea_i\leN\)。思路首先,“排列”本身这个性质是很强的。因为排列本身需要从1开......
  • AT_agc011_d [AGC011D] Half Reflector 题解
    用\(1\)表示A,\(0\)表示B,观察进行一次操作后字符串会发生什么变化。首先当第一个数为\(1\)时,只会将第一个数变为\(0\)。对于剩下的情况,手玩一下可以发现会将第一个数移到末尾,然后将所有数异或\(1\)。先考虑暴力怎么做,可以记一个指针\(i\)和当前应该给全体数异或的值\(......
  • P10856 【MX-X2-T5】「Cfz Round 4」Xor-Forces题解
    题意:给定一个长度为\(n=2^k\)的数组\(a\),下标从\(0\)开始,维护\(m\)次操作:给定\(x\),设数列\(a'\)满足\(a'_i=a_{i\oplusx}\),将\(a\)修改为\(a'\)。其中\(\oplus\)表示按位异或运算。给定\(l,r\),查询\(a\)的下标在\(l,r\)之间的子数组有多少颜色段。不保......
  • [题解]P3225 [HNOI2012] 矿场搭建
    P3225[HNOI2012]矿场搭建挖煤点坍塌相当于把该点和与其相连的边在图上删掉。借用wjyyy的题解,我们定义“叶子连通块”为“只包含\(1\)个割点的点双连通分量”,“非叶子连通块”为“包含\(\ge2\)个割点的点双连通分量”。如下图,橙色点是割点,红色框圈出的是点双,加粗的是叶子连通......
  • P2612 [ZJOI2012] 波浪 题解
    前置知识:连续段dp题目链接:P2612[ZJOI2012]波浪随机一个\(1\)到\(n\)的排列\(P_{1...n}\),问以下式子的值\(\lem\)的概率是多少?\[|P_1-P_2|+|P_2-P_3|+|P_3-P_4|+...+|P_{n-1}+P_n|\]输出一个答案表示概率。保留\(k\)位小数。对于\(40%\)......