训练赛 Grouping(强连通分量缩点 + DAG求最长路)

2024-08-28 10:32

本文主要是介绍训练赛 Grouping(强连通分量缩点 + DAG求最长路),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://acm.sdut.edu.cn:8080/vjudge/contest/view.action?cid=158#problem/F


大致题意:给出n个人和m种关系(ti,si),表示ti的年龄不小于si。问最小能被划分为几个集合,每个集合都要满足里面的人都无法比较。


思路:对于一条路上的点,它们必定不能被划分到同一个集合中,因此原题变为求一条最长路。而题目中有可能出现环。因此,先tarjan缩点转化为DAG,而缩点后的每个点的点权便是该节点中包含的点的个数,然后记忆化求最长路。

PS:该题与上一篇 

uva 11324 The Largest Clique是一样的。该题重在转化。


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <map>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#define LL long long
#define _LL __int64
#define eps 1e-8
#define PI acos(-1.0)
using namespace std;const int INF = 0x3f3f3f3f;
const int maxn = 100010;vector <int> edge[maxn],edge2[maxn];
int n,m;
int dfn[maxn],low[maxn],instack[maxn],dep,scc;
stack <int> st;
int set[maxn],num[maxn];
int d[maxn];void init()
{for(int i = 1; i <= n; i++){edge[i].clear();edge2[i].clear();}memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(instack,0,sizeof(instack));while(!st.empty()) st.pop();dep = 0;scc = 0;memset(num,0,sizeof(num));memset(d,0,sizeof(d));
}void tarjan(int u)
{dfn[u] = low[u] = ++dep;instack[u] = 1;st.push(u);for(int i = 0; i < (int)edge[u].size(); i++){int v = edge[u][i];if(!dfn[v]){tarjan(v);low[u] = min(low[u],low[v]);}else if(instack[v])low[u] = min(low[u],dfn[v]);}if(dfn[u] == low[u]){scc++;int t;while(1){t = st.top();st.pop();instack[t] = 0;set[t] = scc;num[scc]++;if(t == u)break;}}
}void creat()
{for(int u = 1; u <= n; u++){for(int i = 0; i < (int)edge[u].size(); i++){int v = edge[u][i];if(set[u] != set[v])edge2[set[u]].push_back(set[v]);}}
}int dp(int u)
{if(d[u]) return d[u];else if(edge2[u].size() == 0) return d[u] = num[u];int ans = 0;for(int i = 0; i < (int)edge2[u].size(); i++){int v = edge2[u][i];ans = max(ans,dp(v));}return d[u] = ans+num[u];
}int main()
{int u,v;while(~scanf("%d %d",&n,&m)){init();for(int i = 1; i <= m; i++){scanf("%d %d",&u,&v);edge[u].push_back(v);}for(int i = 1; i <= n; i++)if(!dfn[i])tarjan(i);creat();int ans = 0;for(int i = 1; i <= scc; i++){ans = max(ans,dp(i));}printf("%d\n",ans);}return 0;
}



这篇关于训练赛 Grouping(强连通分量缩点 + DAG求最长路)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1114512

相关文章

poj3261(可重复k次的最长子串)

题意:可重复k次的最长子串 解题思路:求所有区间[x,x+k-1]中的最小值的最大值。求sa时间复杂度Nlog(N),求最值时间复杂度N*N,但实际复杂度很低。题目数据也比较水,不然估计过不了。 代码入下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

线性因子模型 - 独立分量分析(ICA)篇

序言 线性因子模型是数据分析与机器学习中的一类重要模型,它们通过引入潜变量( latent variables \text{latent variables} latent variables)来更好地表征数据。其中,独立分量分析( ICA \text{ICA} ICA)作为线性因子模型的一种,以其独特的视角和广泛的应用领域而备受关注。 ICA \text{ICA} ICA旨在将观察到的复杂信号

hihocoder1050 : 树中的最长路

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中,小Ho发现他不仅仅可以拼凑成一棵二叉树!还可以拼凑成一棵多叉树——好吧,其实就是更为平常的树而已。 但是不管怎么说,小Ho喜爱的玩具又升级换代了,于是他更加爱不释手(其实说起来小球和木棍有什么好玩的是吧= =)。小Ho手

POJ1631最长单调递增子序列

最长单调递增子序列 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.util.StringTokenizer;publ

计蒜客 Skiing 最长路

In this winter holiday, Bob has a plan for skiing at the mountain resort. This ski resort has MM different ski paths and NN different flags situated at those turning points. The ii-th path from the

PHP最长单一子串

<?php//方法一$s='abcccddddddcdefg';$max='';while($s!=''){$i=0; while($i<strlen($s) && $s[$i]==$s[0]) $i++;if ($i>strlen($max)){$max=substr($s,0,$i);} $s=substr($s,$i);}echo $m

day-50 求出最长好子序列 I

思路 二维dp,dp[i][h]表示nums[i] 结尾,且有不超过 h 个下标满足条件的最长好子序列的长度(0<=h<=k),二维数组dp初始值全为1 解题过程 状态转换方程: 1.nums[i]==nums[j],dp[i,h]=Math.max(dp[i,h],dp[j,h]+1) 2.nums[i]!=nums[j],dp[i,h]=Math.max(dp[i,h],dp[j,h-1

LeetCode:3177. 求出最长好子序列 II 哈希表+动态规划实现n*k时间复杂度

3177. 求出最长好子序列 II 题目链接 题目描述 给你一个整数数组 nums 和一个非负整数k 。如果一个整数序列 seq 满足在下标范围 [0, seq.length - 2] 中 最多只有 k 个下标i满足 seq[i] != seq[i + 1] ,那么我们称这个整数序列为好序列。请你返回 nums中好子序列的最长长度。 实例1: 输入:nums = [1,2,1,1,3],

Leetcode面试经典150题-128.最长连续序列-递归版本另解

之前写过一篇这个题的,但是可能代码比较复杂,这回来个简洁版的,这个是递归版本 可以看看之前的版本,两个版本面试用哪个都保过 解法都在代码里,不懂就留言或者私信 class Solution {/**对于之前的解法,我现在提供一共更优的解,但是这种可能会比较难懂一些(思想方面)代码其实是很简洁的,总体思想如下:不需要排序直接把所有数放入map,map的key是当前数字,value是当前数开始的