习题:codevs 2822 爱在心中 解题报告
这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页)。
这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联通分量里面只有这一道题。
题目是这样的:
“每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动。爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home。” 在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况)。爱是具有传递性的,即如果A爱B,B爱C,则A也爱C。
如果有这样一部分人,他们彼此都相爱,则他们就超越了一切的限制,用集体的爱化身成为一个爱心天使。
现在,我们想知道在这个爱的国度里会出现多少爱心天使。而且,如果某个爱心天使被其他所有人或爱心天使所爱则请输出这个爱心天使是由哪些人构成的,否则输出-。
这是一个有向图上的问题,这道题很容易看出来一个爱心天使就是一群人互相爱然后组成的有向环。既然是有向的图求强联通分量,套上tarjan就行了。不过因为后面要输出爱心天使是由哪些人构成的,所以,我们需要记录每个人在哪个爱心天使里面,具体tarjan标程就是下面这样:
void dfs(int u){
low[u] = dfn[u] = ++dfs_clock;
s.push(u);
for(int i = ;i < g[u].size();++i){
int v = g[u][i];
if(!dfn[v]){
dfs(v);
low[u] = min(low[u],low[v]);
}
else if(!ind[v]){
low[u] = min(low[u],dfn[v]);
}
}
if(low[u] == dfn[u]){
scc_cnt++;
while(){
int x = s.top();
s.pop();
ind[x] = scc_cnt;
sccno[scc_cnt]++;
if(x == u)break;
}
}
}
void find_scc(int n){
dfs_clock = scc_cnt = ;
for(int i = ;i <= n;++i){
if(!dfn[i])dfs(i);
}
}
如果有不懂的地方,就说明是tarjan算法还是没搞懂,请先搞定tarjan算法的基础再来看这道题。
然后就是求每个爱心天使被多少个人爱着(爱心天使也被属于它自己的人们爱着)。由于爱有传递性,我们很容易能想到传递闭包的问题。具体做法就是:
1.先求出来所有的爱心天使(在这里一个人也当作是一个爱心天使,但是输出爱心天使个数的时候,一个人组成的爱心天使是不算的)和这个爱心天使由多少个人组成。
2.给每个爱心天使编号(缩点),然后建立一个以“被爱”为方向的新的有向图。
3.在新的有向图中跑SPFA(为什么不用Floyd,这个时间复杂度太高了,所以我们还是选择scc_cnt遍的SPFA,时间复杂度最坏也就是O(nke),保证是超不了时间的。SPFA在这里起到的作用就是计算每个爱心天使的爱能否传递到某个天使)。
4.统计计数,如果size[某个爱心天使] == n的话,那么就按编号从小到大遍历每个人输出这个爱心天使由哪些人组成。如果没有任何一个爱心天使的size为n的话,(用一个数记录,如果b == 0)就输出-1.
然后呈现整体代码,还是不是很长,才刚139行。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <set>
#include <queue>
using namespace std;
const int maxn = ;
int dfn[maxn],low[maxn],dfs_clock,n,ind[maxn],m,scc_cnt,a,b,size[maxn],sccno[maxn],tim = ;
struct edge{
int u,v;
edge(int a,int b):u(a),v(b){};
};
struct edges{
int to,next,cost;
}qmap[maxn<<];
vector<int>g[maxn];
vector<int>gk[maxn];
vector<edge>ga;
int d[maxn],h[maxn];
const int INF = ;
stack<int> s;
void add(int u,int v){
qmap[tim].to = v;qmap[tim].cost = ;qmap[tim].next = h[u];h[u] = tim++;
}
void init(int n){
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(ind,,sizeof(ind));
memset(size,,sizeof(size));
memset(sccno,,sizeof(sccno));
memset(h,-,sizeof(h));
for(int i = ;i <= n;++i){
g[i].clear();
gk[i].clear();
}
}
void dfs(int u){
low[u] = dfn[u] = ++dfs_clock;
s.push(u);
for(int i = ;i < g[u].size();++i){
int v = g[u][i];
if(!dfn[v]){
dfs(v);
low[u] = min(low[u],low[v]);
}
else if(!ind[v]){
low[u] = min(low[u],dfn[v]);
}
}
if(low[u] == dfn[u]){
scc_cnt++;
while(){
int x = s.top();
s.pop();
ind[x] = scc_cnt;
sccno[scc_cnt]++;
if(x == u)break;
}
}
}
void find_scc(int n){
dfs_clock = scc_cnt = ;
for(int i = ;i <= n;++i){
if(!dfn[i])dfs(i);
}
}
void spfa(int x){
for(int i = ;i <= scc_cnt;++i){
d[i] = INF;
}
bool visit[maxn];
memset(visit,false,sizeof(visit));
d[x] = ;
queue<int>q;
q.push(x);
visit[x] = true;
while(!q.empty()){
int y = q.front();
q.pop();visit[y] = false;
for(int i = h[y];i != -;i = qmap[i].next){
edges e = qmap[i];
if(d[y] + e.cost < d[e.to]){
d[e.to] = d[y] + e.cost;
if(!visit[e.to]){
q.push(e.to);
visit[e.to] = true;
}
}
}
}
}
void work(int i){
spfa(i);
for(int k = ;k <= scc_cnt;++k){
if(k == i)continue;
if(d[k] == INF)continue;
size[i] += sccno[k];
}
if(size[i] == n){
b = ;
for(int j = ;j <= n;++j){
if(ind[j] == i)printf("%d ",j);
}
printf("\n");
}
return;
}
int main(){
scanf("%d%d",&n,&m);
init(n);
for(int i = ;i <= m;++i){
scanf("%d%d",&a,&b);
g[a].push_back(b);
gk[b].push_back(a);
ga.push_back(edge(b,a));
}
find_scc(n);
int ans = scc_cnt;
for(int i = ;i <= scc_cnt;++i){
if(sccno[i] == )ans--;
}
printf("%d\n",ans);
for(int i = ;i < ga.size();++i){
add(ind[ga[i].u],ind[ga[i].v]);
}
for(int i = ;i <= scc_cnt;++i){
size[i] = sccno[i];
}
b = ;
for(int i = ;i <= scc_cnt;++i){
if(sccno[i] != )work(i);
}
if(b == )printf("-1\n");
return ;
}
这次的解题报告就到这里,蒟蒻继续去刷题了。还有如果有问题的话,请联系我的邮箱PC-worker@outlook.com向我留言。
习题:codevs 2822 爱在心中 解题报告的更多相关文章
- 【CodeVS】2822 爱在心中 [2017年6月计划 强连通分量03]
2822 爱在心中 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description “每个人都拥有一个梦,即使彼此不相同,能够 ...
- codevs & vijos 爱在心中 - Tarjan
描述 “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home.” 在爱的国度里有N个人,在他们的心中都有 ...
- codevs 2822 爱在心中
codevs 2822 爱在心中 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description “每个人都拥有一个梦,即使彼此不相同, ...
- codevs——2822 爱在心中
2822 爱在心中 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description “每个人都拥有一个梦,即使彼此不相 ...
- codevs 2822爱在心中
不想吐槽题目.... /* K bulabula 算法(好像用哪个T bulabula更简单 然而我并不会 - -) 丑陋的处理cnt: Printf时 cnt中 ans[i][0]==1 的删掉 然 ...
- BZOJ 1051 最受欢迎的牛 解题报告
题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4438 Solved: 2353[S ...
- 习题:codevs 1035 火车停留解题报告
本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...
- 习题: codevs 2492 上帝造题的七分钟2 解题报告
这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...
- 习题:codevs 1519 过路费 解题报告
今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...
随机推荐
- atitit。企业的价值观 员工第一 vs 客户第一.docx
atitit.企业的价值观 员工第一 vs 客户第一.docx 1. 客户第一的说法是错误的,员工优先是正确的,理念与价值观1 1.1. 任何一个组织,应该组织成员优先级要比外部成员高才对1 1.2. ...
- Jenkins+MSbuild+SVN实现dotnet持续集成 快速搭建持续集成环境
Jenkins是一个可扩展的持续集成引擎,Jenkins非常易于安装和配置,简单易用,下面开始搭建dotnet持续集成环境 一.准备工作 1.系统管理-->管理插件-->可选插件中找到MS ...
- Android Activity 启动模式和任务栈
在了解了基本的Activity的生命周期后,我们能够很好的在一个Activity上面做相关的业务.但是这是不够的,因为Android通过任务栈来保存整个APP的Activity,合理的调度任务栈才能够 ...
- jquery的html,text,val
.html()用为读取和修改元素的HTML标签 .text()用来读取或修改元素的纯文本内容 .val()用来读取或修改表单元素的value值. 这三个方法功能上的对比 .html(),.text() ...
- AJAX文件上传实践与分析,带HTML5文件上传API。
对于HTML5已经支持AJAX文件上传了,但如果需要兼容的话还是得用一点小技巧的,HTML5等等介绍,先来看看以前我们是怎么写的. 网上可能会有一些叫AJAX文件上传插件,但在AJAX2.0之前是不可 ...
- Android入门(三)Activity-生命周期与启动模式
原文链接:http://www.orlion.ga/432/ 一.活动的生命周期 1.返回栈 Android中的活动是可以重叠的,我们每启动一个新的活动,就会覆盖在原活动之上,然后点击Back键会销毁 ...
- html5遵循的5个设计原则
前面的话 实际上,html5并不是由w3c直接制定的,w3c的方向是xhtml2,而不是html5.当xhtml2脱离现实,无法付诸实践时,w3c工作组才将研究方向转向html5.为什么xhtml2从 ...
- 前端工程师技能之photoshop巧用系列第四篇——图片格式
× 目录 [1]图片格式 [2]保存设置 前面的话 对于前端来说,图片格式是需要重要掌握的知识.本文是photoshop巧用系列第四篇——图片格式 图片格式 目前在前端的开发中常用的图片格式有jpg. ...
- hdu4751Divide Groups(dfs枚举完全图集合或者bfs染色)
/************************************************************************* > File Name: j.cpp > ...
- Angularjs 跳转页面并传递参数的方法总结
http://www.zhihu.com/question/33565135 http://www.codeproject.com/Articles/1073780/ASP-NET-MVC-CRUD- ...