习题: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算法求出来的边,其余的边都可以删掉,于是就有了这 ...
随机推荐
- salesforce 零基础学习(十六)Validation Rules & Date/time
上一篇介绍的内容为Formula,其中的Date/time部分未指出,此篇主要介绍Date/time部分以及Validation rules. 本篇参考PDF: Date/time:https://r ...
- Eclipse中java获得mysql的查询结果集
不废话,先上代码,再上解释说明 package com.ningmeng; import java.sql.*; /** * 1:获取查询结果集 * @author biexiansheng * */ ...
- 部署到IIS报错:HTTP错误500.19,错误代码0x80070021
查看网上IIS7出现这个问题解决办法是: 因为 IIS 7 采用了更安全的 web.config 管理机制,默认情况下会锁住配置项不允许更改.运行命令行 %windir%\system32\inets ...
- javaweb回顾第十篇JSTL
前言:JSTL(JSP Standard Tag Library)JSP标准标签库.它的目的是为了简化JSP的开发,如何没有JSTL可能我们开发的时候就需要写大量的自定义标签,无疑会加大开发难度,有了 ...
- SSRS2:Reporting Service 配置Service Account
1,Service Account SSRS以一个Service方式实现,有三部分组成:Web Service,Report Manager和一个后台的进程,这个Service运行的账号就是Servi ...
- hdu2066一个人的旅行(多源点多汇点的最短路径问题)
/* 思路:多源点,多会点的最短路径! 将最小号-1的节点但最源点,将最大号+1的点当作汇点! 将问题转变成从一个源点到一个汇点的最短路径的问题! 开始忘记初始化vector了,哇了好多次....坑爹 ...
- Android TextView高级特性使用
TextView一般都是用来显示一段文本,这里说的高级特性主要是一些我们平常不太常用的属性.包括文字阴影.自定义字体.html嵌入多格式.字体加粗.插入图片.这些特性平时开发APP的时候,可能一般使用 ...
- PHP的学习--Traits新特性
在阅读yii2源码的时候接触到了trait,就学习了一下,写下博客记录一下. 自 PHP 5.4.0 起,PHP 实现了代码复用的一个方法,称为 traits. Traits 是一种为类似 PHP 的 ...
- 【web前端面试题整理03】来看一点CSS相关的吧
前言 昨天我们整理了14到js的题,今天我们再来整理14到CSS相关的题目,昨天整理时候时间有点晚了我便有点心浮气躁,里面的一些题需要再次解答,好了看看今天有些什么吧. PS:我这里挑一点来做就好了, ...
- Sybase数据库收集表及其索引的统计信息
更新表及其索引的统计信息: update table statistics 表名 go update index statistics 表名 go 建议此操作在闲时操作.