<题目链接>

题目大意:

n个人,m条关系,每条关系a >= b,说明a,b之间是可比较的,如果还有b >= c,则说明b,c之间,a,c之间都是可以比较的。问至少需要多少个集合使得每个集合内的人都是不可比较的。

解题分析:

将所给的关系当成有向边,根据题意,同一强连通分量中的任意两点不能分到一组,所以我们先将整张图进行缩点,缩点后"点"的中点的数量当做点权,然后就可以转化为最长路的求解了。这里比较难想,因为同一连通分量中的点不能在一组,所以必然要将它们全部排成一条。因为要求最少分成的组,所以我们只需要将整张图的最长关键路径(最大点权和的路径)找出即可,这样可以将不在关键路径上的"点"中的所有的点与最长路径上的不同点分配到一组,因为它们不属于一个连通分量,所以这样分配,每组之间的所有点仍然是不可比较的。又因为这是最长路径,所以每次必然能够最长路径之外的"点"中所有的点与最短路径上的点一 一分配到一组。

 #include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
const int N = 1e5+;
const int M = 3e5+;
struct Edge{
int v, nxt;
} edge[M], edg[M];
int n,m,tott, tot, ord, scc, top;
int cnt[N], dp[N], head[N], hea[N], vis[N], deg[N], dfn[N], low[N], belong[N],stk[N]; void init(){
tot = scc = tott = ord = top = ;
memset(head, -, sizeof(head));
memset(hea, -, sizeof(hea));
memset(dfn, , sizeof(dfn));
memset(dp, , sizeof(dp));
memset(cnt,,sizeof(cnt));
}
void Add(int u, int v) {
edge[tot].v = v; edge[tot].nxt = head[u];
head[u] = tot++;
}
void add(int u, int v) {
edg[tott].v = v; edg[tott].nxt = hea[u];
hea[u] = tott++;
}
void tarjan(int u) {
dfn[u] = low[u] = ++ord;
stk[++top]=u; vis[u] = ;
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(vis[v])low[u]=min(low[u],dfn[v]);
}
if(low[u] == dfn[u]) {
++scc;
while(true){
int v=stk[top--];
belong[v] = scc;
cnt[scc]++;
vis[v] = ;
if(v==u)break;
}
}
}
//将"点"中点的数量作为这个点的点权,然后求出最大点权的路径
//dp[u]表示,以u为起点的最长路径
int DFS(int u) {
if(dp[u]) return dp[u];
int ans = cnt[u];
for(int i = hea[u]; ~i; i = edg[i].nxt) {
int v = edg[i].v;
ans = max(ans, DFS(v) + cnt[u]);
}
return dp[u] = ans;
}
int main() {
while(~scanf("%d%d", &n, &m)) {
init();
for(int i = ; i < m; i++) {
int u,v;scanf("%d%d", &u, &v);
Add(u, v);
}
for(int i = ; i <= n; i++)
if(!dfn[i]) tarjan(i);
for(int u = ; u <= n; u++)
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(belong[u] != belong[v]) {
add(belong[u], belong[v]);
}
}
int ans = -;
for(int i = ; i <= scc; i++)
ans = max(ans, DFS(i)); //所有点为起点的最长路径即为整张图的最长路径
printf("%d\n", ans);
}
}

2018-11-26

ZOJ 3795 Grouping (强连通缩点+DP最长路)的更多相关文章

  1. UVA11324 The Largest Clique (强连通缩点+DP最长路)

    <题目链接> 题目大意: 给你一张有向图 G,求一个结点数最大的结点集,使得该结点集中的任意两个结点 u 和 v 满足:要么 u 可以达 v,要么 v 可以达 u(u,v相互可达也行). ...

  2. Grouping ZOJ - 3795 (tarjan缩点求最长路)

    题目链接:https://cn.vjudge.net/problem/ZOJ-3795 题目大意:给你n个人,m个关系, 让你对这个n个人进行分组,要求:尽可能的分组最少,然后每个组里面的人都没有关系 ...

  3. zoj 3795 Grouping tarjan缩点 + DGA上的最长路

    Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Submit Status Practic ...

  4. BZOJ 5450 轰炸 (强连通缩点+DAG最长路)

    <题目链接> 题目大意: 有n座城市,城市之间建立了m条有向的地下通道.你需要发起若干轮轰炸,每轮可以轰炸任意多个城市.但每次轰炸的城市中,不能存在两个不同的城市i,j满足可以通过地道从城 ...

  5. ZOJ 3795 Grouping 强连通分量-tarjan

    一开始我还天真的一遍DFS求出最长链以为就可以了 不过发现存在有向环,即强连通分量SCC,有向环里的每个点都是可比的,都要分别给个集合才行,最后应该把这些强连通分量缩成一个点,最后保证图里是 有向无环 ...

  6. 【bzoj1179】[Apio2009]Atm Tarjan缩点+Spfa最长路

    题目描述 输入 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每 ...

  7. Tarjan缩点+Spfa最长路【p3627】[APIO2009] 抢掠计划

    Description Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机.令人奇怪的是,Siruseri ...

  8. Gym - 101170B British Menu (强连通缩点+dp)

    题意:求一个有向图上的最长路(每个强连通分量的点不超过5个) 首先对强连通分量缩点,暴力预处理出len[k][i][j]表示第k个强连通分量里的第i个点和第j个点之间的最长路径,设状态(k,i,f)表 ...

  9. ZOJ 3795 Grouping(scc+最长路)

    Grouping Time Limit: 2 Seconds      Memory Limit: 65536 KB Suppose there are N people in ZJU, whose ...

随机推荐

  1. swift 实践- 04 -- UIButton

    import UIKit class ViewController: UIViewController { // 按钮的创建 // UIButtonType.system: 前面不带图标, 默认文字为 ...

  2. 【MySql】Order By 排序

    你可以使用任何字段来作为排序的条件,从而返回排序后的查询结果. 你可以设定多个字段来排序. 你可以使用 ASC 或 DESC 关键字来设置查询结果是按升序或降序排列. 默认情况下,它是按升序排列. 你 ...

  3. checkstyle.xml Code Style for Eclipse

    1. Code Templates [下载 Code Templates] 打开 Eclipse -> Window -> Preferences -> Java -> Cod ...

  4. Confluence 6 访问日志脚本

    日志访问脚本在连接:https://confluence.atlassian.com/download/attachments/133267635/Atlassian-accessLogScripts ...

  5. 兼容性很好的纯css圆角

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...

  6. python垃圾回收机制:引用计数 VS js垃圾回收机制:标记清除

    js垃圾回收机制:标记清除 Js具有自动垃圾回收机制.垃圾收集器会按照固定的时间间隔周期性的执行. JS中最常见的垃圾回收方式是标记清除. 工作原理 当变量进入环境时,将这个变量标记为"进入 ...

  7. GIT的基本使用及应用场景

    一.什么是GIT? Git 是一个开源的分布式版本控制软件,用以有效.高速的处理从很小到非常大的项目版本管理. GitHub.GitCafe.BitBucket和GitLab等是基于Git版本控制的远 ...

  8. fdisk命令

    fdisk -l命令详解 Disk /dev/sda: 53.7 GB, 53687091200 bytes 块设备名称为/dev/sda,此设备的大小为53.7GB,这个数字不是特别精确,我系统是5 ...

  9. 微信小程序开发 如何退出当前页面

    默认是在首页 wx.navigateBack({     delta: -1 });     详情参考. https://mp.weixin.qq.com/debug/wxadoc/dev/api/u ...

  10. robocopy的用法,数据库局域网备份

    robocopy,我主要是用来进行局域网数据库备份使用,不得不说这个小工具速度还是蛮快的,同时属于系统内置功能,用着还算方便. 这项功能就是RoboCopy,它是一个命令行的目录复制命令,自从Wind ...