ZOJ 3795 Grouping
大致题意是给n个人和m组关系,每组关系都是两个人s和t,表示s年龄不小于t的年龄,然后让你把这n个人分组,使得任何一个组里面的任意两人都不能直接或间接的得出这两个人的年龄大小关系。
思路:根据给出的关系建图,问题转化为求图里面的一个最长链。考虑简单情形:图里面没有回路,那么直接dp+记忆化搜索就OK了,len[u] = max(len[u],len[v] + 1),(u,v相邻)。若有回路,那么利用tarjan进行缩点,把一个强连通分量里面的所有点缩成一个点,该点的权重就是分量里面点的个数,仍利用上述方法求解即可 len[u] = max(len[u],len[v] + w[u])。
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100010;
int ind, top, cnt;
int vis[MAXN], len[MAXN], head[MAXN], shead[MAXN];
int dfn[MAXN], low[MAXN], st[MAXN], num[MAXN], w[MAXN];
struct Edge{
int to, next;
};
Edge edge[3*MAXN], sedge[3*MAXN];
void addEdge(int u, int v, int k){
edge[k].to = v;
edge[k].next = head[u];
head[u] = k;
}
void saddEdge(int u, int v, int k){
sedge[k].to = v;
sedge[k].next = shead[u];
shead[u] = k;
}
void tarjan(int u){
dfn[u] = low[u] = ++ind;
vis[u] = 1, st[++top] = u;
for(int i = head[u]; ~i; i = edge[i].next){
int v = edge[i].to;
if(!dfn[v]){
tarjan(v);
low[u] = min(low[u], low[v]);
}else if(vis[v]) low[u] = min(low[u], dfn[v]);
}
int tmp;
if(low[u] == dfn[u]){
do{
tmp = st[top--];
num[tmp] = cnt;
vis[tmp] = 0;
}while(tmp != u);
cnt ++;
}
}
int dfs(int u){
vis[u] = 1, len[u] = w[u];
for(int i = shead[u]; ~i; i = sedge[i].next){
int v = sedge[i].to;
if(vis[v]) len[u] = max(len[u], len[v] + w[u]);
else len[u] = max(len[u], dfs(v) + w[u]);
}
return len[u];
}
int solve(int n){
int k = 1;
ind = top = 0;
cnt = 1;
memset(w, 0, sizeof(w));
memset(dfn, 0, sizeof(dfn));
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i ++)
if(!dfn[i]) tarjan(i);
memset(shead, -1, sizeof(shead));
for(int i = 1; i <= n; i ++){
w[num[i]] ++;
for(int j = head[i]; ~j; j = edge[j].next){
int u = edge[j].to;
if(num[i] != num[u]) saddEdge(num[i], num[u], k++);
}
}
int ans = 1;
memset(vis, 0, sizeof(vis));
for(int i = 1; i < cnt; i ++){
if(!vis[i]) dfs(i);
ans = max(ans, len[i]);
}
return ans;
}
int main(){
int n, m;
#ifndef ONLINE_JUDGE
freopen("in.cpp", "r", stdin);
#endif
while(~scanf("%d%d", &n, &m)){
int u, v;
memset(head, -1, sizeof(head));
for(int i = 1; i <= m; i ++){
scanf("%d%d", &u, &v);
addEdge(v, u, i);
}
printf("%d\n", solve(n));
}
return 0;
}
ZOJ 3795 Grouping的更多相关文章
- zoj 3795 Grouping tarjan缩点 + DGA上的最长路
Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu Submit Status Practic ...
- ZOJ 3795 Grouping(scc+最长路)
Grouping Time Limit: 2 Seconds Memory Limit: 65536 KB Suppose there are N people in ZJU, whose ...
- ZOJ 3795 Grouping 求最长链序列露点拓扑
意甲冠军:特定n积分.m向边条. 该点被划分成多个集合随机的每个集合,使得2问题的关键是无法访问(集合只能容纳一个点) 问至少需要被分成几个集合. 假设没有戒指,接着这个话题正在寻求产业链最长的一个有 ...
- ZOJ 3795 Grouping(Tarjan收缩点+DAG)
Suppose there are N people in ZJU, whose ages are unknown. We have some messages about them. The i-t ...
- ZOJ 3795 Grouping (强连通缩点+DP最长路)
<题目链接> 题目大意: n个人,m条关系,每条关系a >= b,说明a,b之间是可比较的,如果还有b >= c,则说明b,c之间,a,c之间都是可以比较的.问至少需要多少个集 ...
- ZOJ 3795 Grouping 强连通分量-tarjan
一开始我还天真的一遍DFS求出最长链以为就可以了 不过发现存在有向环,即强连通分量SCC,有向环里的每个点都是可比的,都要分别给个集合才行,最后应该把这些强连通分量缩成一个点,最后保证图里是 有向无环 ...
- Grouping ZOJ - 3795 (tarjan缩点求最长路)
题目链接:https://cn.vjudge.net/problem/ZOJ-3795 题目大意:给你n个人,m个关系, 让你对这个n个人进行分组,要求:尽可能的分组最少,然后每个组里面的人都没有关系 ...
- ZOJ 3795:Grouping(缩点+最长路)
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5303 题意:有n个人m条边,每条边有一个u,v,代表u的年龄大于等于v,现在要 ...
- 2014 Super Training #8 G Grouping --Tarjan求强连通分量
原题:ZOJ 3795 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3795 题目大意:给定一个有向图,要求把点分为k个集 ...
随机推荐
- Qt-获取主机网络信息之QHostInfo
Qt中提供了几个用于获取主机网络信息的类,包括QHostInfo.QHostAddress.QNetworkInterface以及QNetworkAddress.在本节中,我将在这里总结QHostIn ...
- Apose 套打
给web添加一个dll引用:Apose.Words 下载链接:http://yunpan.cn/cA7v6uceM6KVw 提取码 11df 在Global.asax里面的Application_S ...
- [转]内嵌WORD/OFFICE的WINFORM程序——DSOFRAMER使用小结
最近一直想用VC#2005做个内嵌WORD/OFFICE的WINFORM程序,目前主要有以下解决途径: 1.直接通过API把WORD/OFFICE的窗口句柄给放到WINFORM中(感觉较为复杂): 2 ...
- 长达半年的苹果发布会:亮点与槽点(iPhone5s,iPhone5c)
不知出于什么原因,今天凌晨召开的苹果发布会并没有视频直播,所以大家都守着The Verge家的图文直播.结果,苹果再一次用事实证明了他们没有保密体系,或者,故意没有保密体系. 整场发布会正经的亮点如下 ...
- <三> jQuery 选择器
jQuery 选择器选择需要应用效果的元素,jQuery 元素选择器和属性选择器允许您通过标签名.属性名或内容对 HTML 元素进行选择.选择器允许您对 HTML 元素组或单个元素进行操作. 元素选择 ...
- stdout 编码 vim 删除左边,右边
sys.stdout = codecs.getwriter('utf8')(sys.stdout) vimdic['kkkk'] = qqqqqdic['bbbb'] = aaaaaadic['kkk ...
- C#虚方法virtual详解
转: http://www.cnblogs.com/jason_yjau/archive/2009/08/25/1553949.html C#虚方法virtual详解 在C++.Java等众多OOP语 ...
- php截取小时和分钟,在进行和其它时间段的比较
用php截取时间的小时和分钟,然后判断这个时间是不是在 8:00到11:30之间,用php应该怎么写? date_default_timezone_set("Asia/Shanghai&qu ...
- Jmeter 执行java脚本结束时提示:he JVM should have exitted but did not
使用jmeter执行java协议测试结束时会提示:he JVM should have exitted but did not ,jmeter2.11以后的可以 通过设置: jmeteren ...
- [wikioi]二叉树最大宽度和高度
简单的DFS,用数组w记录每一层的宽度就行了,就是遇到一层就++.中间发现在C++里面,如果int未初始化就是用也是有异常的.还有二叉树的数组表示时,从1开始计数会比较好.还有后来学会了数组这样的初始 ...