codevs & vijos 爱在心中 - Tarjan
描述
“每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动。爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home。”
在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况)。爱是具有传递性的,即如果A爱B,B爱C,则A也爱C。
如果有这样一部分人,他们彼此都相爱,则他们就超越了一切的限制,用集体的爱化身成为一个爱心天使。
现在,我们想知道在这个爱的国度里会出现多少爱心天使。而且,如果某个爱心天使被其他所有人或爱心天使所爱则请输出这个爱心天使是由哪些人构成的,否则输出-1。
格式
输入格式
第1行,两个数N、M,代表爱的国度里有N个人,爱的关系有M条。
第2到第M+1行,每行两个数A、B,代表A爱B。
输出格式
第1行,一个数,代表爱的国度里有多少爱心天使。
第2行,如果某个爱心天使被其他所有人和爱心天使所爱则请输出这个爱心天使是由哪些人构成的(从小到大排序),否则输出-1。
样例1
样例2
样例输入2
3 3
1 2
2 1
2 3
样例输出2
1
-1
限制
各个测试点1s
提示
对于40%的数据 N<=10 M<=100
对于80%的数据 N<=100 M<=1000
对于100%的数据 N<=1000 M<=10000
来源
Cai0715 原创
NOIP 2009·Dream Team 模拟赛 第一期 第四题
(转自 https://vijos.org/p/1626 )
这题虽然看起来很高大上的样子但是只要想通了就不怎么难了
很明显第二问要求的点是强连通分量4,它有什么样的特点呢?
出度为0。如果它的出度不是0会发生什么(其他强连通分量的出度都不为0)?
就会和其他强连通分量形成一个更大的强连通分量,如果存着这个的话,tarjan
算法会先就把它求出来,也就是说这种情况是不可能
还有一种情况,就是图不连通:

这时候可以发现出度为0的点有两个,但是我们该输出-1
于是我们得到出度为0的点只能有1个,否则输出-1,至于输出
成员嘛。。直接照着belong数组扫一道,就行了
Code:
/*
*codevs.cn &Vijos.org
*Problem#2822 & Problem#1626
*Accepted & Accepted
*Time:2ms & 0ms
*Memory:256k & 584k
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#define _min(a,b) ((a)<(b))?(a):(b)
using namespace std;
typedef bool boolean;
typedef class Edge{
public:
int end;
int next;
Edge():end(),next(){}
Edge(int end,int next):end(end),next(next){}
}Edge;
Edge *edge;
int n,m;
int *head;
int top;
inline void addEdge(int from,int end){
top++;
edge[top].next=head[from];
edge[top].end=end;
head[from]=top;
}
//Tanjan算法,变量
boolean *visited;
boolean *isCir;
int *visitID;
int *exitID;
int entryed;
stack<int> sta;
int *belong;
boolean *inStack;
int _count;
void getSonMap(int end){
int now=-;
int exits=;
while(now!=end){
now=sta.top();
belong[now]=end;
inStack[now]=false;
exits++;
sta.pop();
}
if(exits>){
_count++;
isCir[now]=true;
}
}
void Tarjan(const int pi){
int index=head[pi];
visitID[pi]=++entryed;
exitID[pi]=visitID[pi];
visited[pi]=true;
inStack[pi]=true;
sta.push(pi);
while(index!=){
if(!visited[edge[index].end]){
Tarjan(edge[index].end);
exitID[pi]=_min(exitID[pi],exitID[edge[index].end]);
}else if(inStack[edge[index].end]){
exitID[pi]=_min(exitID[pi],visitID[edge[index].end]);
}
index=edge[index].next;
}
if(exitID[pi]==visitID[pi]){
getSonMap(pi);
}
}
int *outgoing;
void rebuild(){
for(int i=;i<=n;i++){
for(int j=head[i];j!=;j=edge[j].next){
if(belong[edge[j].end]!=belong[i])
outgoing[belong[i]]++;
}
}
int result = ;
int id;
for(int i=;i<=n;i++){
if(outgoing[i]==&&isCir[i]){
result++;
id=belong[i];
}
}
if(result==){
for(int i=;i<=n;i++){
if(belong[i]==id){
printf("%d ",i);
}
}
}else{
printf("-1");
}
}
int main(){
cin>>n>>m;
head=new int[(const int)(n+)];
edge=new Edge[(const int)(m+)];
visited=new boolean[(const int)(n+)];
visitID=new int[(const int)(n+)];
exitID=new int[(const int)(n+)];
belong=new int[(const int)(n+)];
inStack=new boolean[(const int)(n+)];
isCir=new boolean[(const int)(n+)];
memset(head,,sizeof(int)*(n+));
memset(visited,false,sizeof(boolean)*(n+));
memset(inStack,false,sizeof(boolean)*(n+));
memset(isCir,false,sizeof(boolean)*(n+));
for(int i=;i<=m;i++){
int f,e;
scanf("%d%d",&f,&e);
addEdge(f,e);
}
for(int i=;i<=n;i++) belong[i]=i;
for(int i=;i<=n;i++){
if(!visited[i])
Tarjan(i);
}
cout<<_count<<endl;
delete[] visited;
delete[] inStack;
// visited=new boolean[(const int)(n+1)];
// inStack=new boolean[(const int)(n+1)];
// memset(visited,false,sizeof(boolean)*(n+1));
// memset(inStack,false,sizeof(boolean)*(n+1));
outgoing=new int[(const int)(n+)];
memset(outgoing,,sizeof(int)*(n+));
rebuild();
return ;
}
codevs & vijos 爱在心中 - Tarjan的更多相关文章
- 习题:codevs 2822 爱在心中 解题报告
这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...
- 【CodeVS】2822 爱在心中 [2017年6月计划 强连通分量03]
2822 爱在心中 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description “每个人都拥有一个梦,即使彼此不相同,能够 ...
- codevs 2822 爱在心中
codevs 2822 爱在心中 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description “每个人都拥有一个梦,即使彼此不相同, ...
- codevs——2822 爱在心中
2822 爱在心中 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description “每个人都拥有一个梦,即使彼此不相 ...
- codevs 3165 爱改名的小融2
3149 爱改名的小融 2 http://codevs.cn/problem/3149/ 题目描述 Description Wikioi上有个人叫小融,他喜欢改名.现在他的要求变了,只要是英文字母就是 ...
- 【codevs2822】爱在心中 tarjan 缩点+理解
[codevs2822]爱在心中 2014年1月26日5580 题目描述 Description “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸, ...
- codevs 2822爱在心中
不想吐槽题目.... /* K bulabula 算法(好像用哪个T bulabula更简单 然而我并不会 - -) 丑陋的处理cnt: Printf时 cnt中 ans[i][0]==1 的删掉 然 ...
- vijos p1027休息中的小呆
休息中的小呆 描述 当大家在考场中接受考验(折磨?)的时候,小呆正在悠闲(欠扁)地玩一个叫“最初梦想”的游戏.游戏描述的是一个叫pass的有志少年在不同的时空穿越对抗传说中的大魔王chineseson ...
- codevs 2277 爱吃皮蛋的小明(水题日常)
时间限制: 1 s 空间限制: 32000 KB 题目等级 : 白银 Silver 题目描述 Description 小明特别爱吃蛋,特别是皮蛋.他一次可以吃一个蛋或者两个蛋(整个吞下去),而且他 ...
随机推荐
- linux系统下添加计划任务执行php文件方法
在web开发过程中,经常需要设定一些定期执行的任务,比如商品定时上下架.我们以php文件为例,讲解linux下的计划任务,来看看吧 在web开发过程中,经常需要设定一些定期执行的任务,比如商品定时 ...
- 2018/03/26 每日一个Linux命令 之 du
昨天使用 df 查看了磁盘空间中所有的容量. 今天学习 du 查看目录或者文件的大小. du会显示指定的目录或文件所占用的磁盘空间. -- du命令用来查看目录或文件所占用磁盘空间的大小.常用选项组合 ...
- How Many Answers Are Wrong----hdu3038(并查集)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038 题意:数组第 a 个元素到第 b 个元素之间的和为sum: 求有几句话是假的,如果与前面的话有冲 ...
- windows使用方法
1:截图搜索英文单词:snipping tool 2: 修改语言,搜索language 3:关闭fn键,按键 fn+esc(fnlock). 就可以将fn关闭和开启.
- 【Cocos2dx 3.3 Lua】触屏事件
cocos2dx 3.x触屏时间分为单点触摸和多点触摸: 单点触摸:(即只有注册的Layer才能接收触摸事件) 多点触摸点单用法(多个Layer获取屏幕事件): ...
- [LeetCode] 221. Maximal Square _ Medium Tag: Dynamic Programming
Given a 2D binary matrix filled with 0's and 1's, find the largest square containing only 1's and re ...
- linq to sql 左联接出错,未将对象引用设置到实例
var result = from a in model join b in orderDetailModel on a.FoodMenuID equals b.FoodMenuID into g f ...
- mui笔记
1.关闭当前页面执行上一个页面的方法 var preview = plus.webview.currentWebview().opener() //获取当前窗口的创建者,即A preview.eval ...
- 圆锥体完全均衡下重力异常正演 [MATLAB]
在完全均衡的模型下,若地表有一圆锥体(山峰等),计算跨越山顶的截面上所得到的各种重力异常. 地壳密度 $kg\cdot m^{-3}$ 上地幔密度 $g\cdot cm^{-3}$ 地表地形圆锥体半径 ...
- 定时器事件QtimerEvent 随机数 qrand Qtimer定时器
QTimerEvent类:定时器事件.QObject的子类都可使用 int QObject::startTimer(int interval)[参数:毫秒][返回值:定时器整型编号]来开启一个定时器 ...