首页 > 其他分享 >Codeforces 1900E Transitive Graph

Codeforces 1900E Transitive Graph

时间:2023-12-23 14:11:06浏览次数:38  
标签:int Graph mn Codeforces id maxn low Transitive mx

考虑题目的限制条件:存在 $a\to b, b\to c$ 的边,就会有 $a\to c$ 的边。
考虑 $p_{1\sim k}$,满足这 $k$ 个点按顺序组成了一个环且无重点。
那么 $p_1\to p_2, p_2\to p_3$,就有 $p_1\to p_3$,又有 $p_3\to p_4$,所以有 $p_1\to p_4$。以此类推,会发现 $\forall i, j\in [1, k], i\not = j$,都存在 $i\to j, j\to i$。
那么就说明 $\forall i, j\in [1, k], i\not = j$,都存在 $i\to j$ 且能走完这 $k$ 个点且不重的路径。

于是考虑缩点,接下来图变成 $\text{DAG}$,就可以在 $\text{DAG}$ 上跑对应的拓扑。

但是有个问题,有没有可能存在 $a\to b\to c$ 的边,但需要把 $b$ 所在的强连通分量走完导致回不了 $b$ 就走不了了。
容易发现是不会的,首先若 $b$ 所在的强连通分量里只有 $b$ 显然满足。
否则随意从 $b$ 所在的强连通分量里找出一个点 $d(d\not = b)$,因为存在 $b\to d$,所以就存在 $d\to c$,这时候就可以扩展为 $a\to b\to d\to c$,同时前面提到了强连通分量里肯定存在 $b\to d$ 且能走完强连通分量里所有点且不重的路径,所以不会存在问题。

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

#include<bits/stdc++.h>
using i64 = long long;
const int limn = 2e5, maxn = limn + 10;
std::vector<int> E[maxn], G[maxn];
i64 w[maxn], sum[maxn];
int dfn[maxn], low[maxn], dt, fa[maxn], ft, stk[maxn], top, ins[maxn], siz[maxn];
void dfs(int u) {
	dfn[u] = low[u] = ++dt, stk[++top] = u, ins[u] = 1;
	for (int v : E[u]) ! dfn[v] ? (dfs(v), low[u] = std::min(low[u], low[v]), 1) : (low[u] = std::min(low[u], ins[v] ? dfn[v] : low[u]), 1);
	if (low[u] != dfn[u]) return ;
	G[++ft].clear(), siz[ft] = 0, sum[ft] = 0;
	do {fa[stk[top]] = ft, ins[stk[top]] = 0, siz[ft]++, sum[ft] += w[stk[top]];} while (stk[top--] != u);
}
int mx[maxn], deg[maxn]; i64 mn[maxn];
auto solve = []() {
	int n, m; scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) scanf("%lld", &w[i]);
	for (int i = 1; i <= n; i++) E[i].clear();
	for (int i = 1; i <= m; i++) {
		int x, y; scanf("%d%d", &x, &y);
		E[x].push_back(y);
	}
	for (int i = 1; i <= n; i++) dfn[i] = 0;
	dt = ft = 0;
	for (int i = 1; i <= n; i++) ! dfn[i] && (dfs(i), 1);
	for (int u = 1; u <= n; u++) for (int v : E[u])
		fa[u] != fa[v] && (G[fa[u]].push_back(fa[v]), deg[fa[v]]++, 1);
	static std::queue<int> q;
	for (int i = 1; i <= ft; i++) mx[i] = 0, mn[i] = 0;
	for (int i = 1; i <= ft; i++) ! deg[i] && (q.push(i), 1);
	while (! q.empty()) {
		int u = q.front(); q.pop();
		mx[u] += siz[u], mn[u] += sum[u];
		for (int v : G[u]) {
			(mx[u] > mx[v] || (mx[u] == mx[v] && mn[u] < mn[v])) && (mx[v] = mx[u], mn[v] = mn[u], 1);
			! (--deg[v]) && (q.push(v), 1);
		}
	}
	int id = 1;
	for (int i = 2; i <= ft; i++) (mx[i] > mx[id] || (mx[i] == mx[id] && mn[i] < mn[id])) && (id = i, 1);
	printf("%d %lld\n", mx[id], mn[id]);
};
int main() {
	int T; scanf("%d", &T);
	while (T--) solve();
	return 0;
}

标签:int,Graph,mn,Codeforces,id,maxn,low,Transitive,mx
From: https://www.cnblogs.com/rizynvu/p/17923084.html

相关文章

  • [Qt5] QGraphics图形视图框架概述(Item、Scene和View)
    作者:丶布布文章预览:......
  • Codeforces Round 651 (Div. 2)C. Number Game(数学思维数论)
    C.NumberGame我们考虑那些状态是必胜态我的回合时n为奇数(除1外),直接除以n则必胜下面偶数的情况稍复杂偶数我们能进行的操作只有除以一个奇数,需要考虑怎么把当前状态变为对手的必败态偶数一定含2的因子,\(n=2^k*q,q为奇数\)当\(k=1时如果q\)是一个质数那么只能除一次q这样......
  • [Codeforces] CF1579C Ticks
    CF1579CTicks题意\(n\timesm\)的棋盘,左上角和右下角坐标分别为\((1,1),(n,m)\),一开始每个格子为白色。每次操作可以选择一个格子\((x,y)\)以及左上角和右上角方向的\(d\)个连续格子染成黑色,并将其称为一个大小为\(d\)的对勾图案。如果多个对勾图案重复对一个格......
  • [Codeforces] CF1811E Living Sequence
    CF1811ELivingSequence这道题洛谷题解的思路比我的更好,可以参考一下题解,但是没人提到我这种做法题意给定一个正整数\(k\)\((1\lek\le10^{12})\),请你输出第\(k\)个数字里没有4的正整数。思路设\(f_i\)表示前\(10^i\)个\(i\)位数里边不含4的数的个数,列举几个如......
  • [Codeforces] CF1817A Almost Increasing Subsequence
    CF1817AAlmostIncreasingSubsequence题意给定长度为\(n\)一个序列\(a\)以及\(q\)次询问,每次询问给出\(l\)和\(r\),找出序列\(a\)在\([l,r]\)内最长的几乎递增子序列。对于几乎递增的定义:如果一个序列中不存在连续的三个数\(x\),\(y\),\(z\),使得\(x\gey\ge\......
  • Codeforces Round 916 (Div. 3)
    目录写在前面ABCDE1/E2FG1G2写在最后写在前面比赛地址:https://codeforces.com/contest/1914。第二天没早八打个div3休闲娱乐保持下手感,然而div3都AK不了了,纯纯废物一个,天天上大学导致的。唉,一学期碰上好几个byd恼弹老师,大学一秒也不想上了,折磨。马娘台服马上1.5周......
  • Educational Codeforces Round 160 (Rated for Div. 2)
    A.RatingIncrease字符串处理#include<bits/stdc++.h>usingnamespacestd;voidsolve(){ strings; cin>>s; intn=s.size(); s=""+s; for(inti=1;i<=n-1;i++){ stringt=""; for(intj=1;j<=i;j++){ t=t+s[j]; } ......
  • Codeforces Round 916 (Div. 3)
    A.ProblemsolvingLogmap枚举字母#include<bits/stdc++.h>usingnamespacestd;voidsolve(){ intn; strings; cin>>n>>s; intans=0; s=""+s; map<char,int>mp; for(inti=1;i<=n;i++){ mp[s[i]]++; } for(autoc:mp)......
  • Codeforces Round 916 (Div. 3)(A~E2)
    A统计一下每个字母的出现次数然后输出即可#include<bits/stdc++.h>#definerep(i,a,b)for(registerinti=(a);i<=(b);++i)#definefep(i,a,b)for(registerinti=(a);i>=(b);--i)#definelsp<<1#definersp<<1|1#definePIIpair<int,int&......
  • [Codeforces] CF1795C Tea Tasting
    CF1795CTeaTasting题意有\(n\)个人和\(n\)杯茶,第\(i\)个人每次会喝\(b_i\)毫升的茶。第\(i\)杯茶有\(a_i\)毫升。总共会喝\(n\)轮茶,第\(j\)轮第\(i\)个人会尝试喝第\(i+1-j\)杯茶。喝的量为\(\min(a_{i+1-j},b_i)\)毫升,并且使\(a_{i+1-j}\)减少\(\mi......