这次的解题报告是有关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 爱在心中 解题报告的更多相关文章

  1. 【CodeVS】2822 爱在心中 [2017年6月计划 强连通分量03]

    2822 爱在心中 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond         题目描述 Description “每个人都拥有一个梦,即使彼此不相同,能够 ...

  2. codevs & vijos 爱在心中 - Tarjan

    描述 “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home.” 在爱的国度里有N个人,在他们的心中都有 ...

  3. codevs 2822 爱在心中

    codevs 2822 爱在心中  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description “每个人都拥有一个梦,即使彼此不相同, ...

  4. codevs——2822 爱在心中

    2822 爱在心中  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description “每个人都拥有一个梦,即使彼此不相 ...

  5. codevs 2822爱在心中

    不想吐槽题目.... /* K bulabula 算法(好像用哪个T bulabula更简单 然而我并不会 - -) 丑陋的处理cnt: Printf时 cnt中 ans[i][0]==1 的删掉 然 ...

  6. BZOJ 1051 最受欢迎的牛 解题报告

    题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4438  Solved: 2353[S ...

  7. 习题:codevs 1035 火车停留解题报告

    本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...

  8. 习题: codevs 2492 上帝造题的七分钟2 解题报告

    这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...

  9. 习题:codevs 1519 过路费 解题报告

    今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...

随机推荐

  1. Atitit 代理CGLIB 动态代理 AspectJ静态代理区别

    Atitit 代理CGLIB 动态代理 AspectJ静态代理区别 1.1. AOP 代理主要分为静态代理和动态代理两大类,静态代理以 AspectJ 为代表:而动态代理则以 spring AOP 为 ...

  2. ASP.NET MVC 微信公众号支付,微信公众平台配置

    微信公众号支付,首先要登录微信公众号进行配置: 第一步:配置网页授权域名

  3. Highcharts结合PhantomJS在服务端生成高质量的图表图片

    项目背景 最近忙着给部门开发一套交互式的报表系统,来替换原有的静态报表系统. 老系统是基于dotnetCHARTING开发的,dotnetCHARTING的优势是图表类型丰富,接口调用简单,使用时只需 ...

  4. spring 源码分析之BeanPostProcessor

    1.官方解答: Factory hook that allows for custom modification of new bean instances, e.g. checking for ma ...

  5. Android UI设计中一些不错的示例及第三方控件

    1.二级ListView自定义布局ExpandableListView http://pan.baidu.com/s/1mhlJh12 密码:nhc2 2.ListView实现各种动画效果ListVi ...

  6. HTML5移动Web开发(三)——在移动网站中使用HTML5

    创建一个简单得HTML5页面ch01e2.html <html> <head> <meta name="viewport" content=" ...

  7. Sass细节一变量

    同步发布在个人站 变量 局部变量和全局变量的定义 Sass的变量是用$申明的,有局部变量(选择器内部的变量)和全局变量(不在任何选择器内的变量).例如: //这里$width就是全局变量 $width ...

  8. 【转】FastCgi与PHP-fpm关系

    刚开始对这个问题我也挺纠结的,看了<HTTP权威指南>后,感觉清晰了不少. 首先,CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的,方便CGI程序的编写者. ...

  9. Elasticsearch——集群相关的配置

    cluster模块主要用于控制分片在节点上如何进行分配,以及何时进行重新分配 概览 下面的一些资料可以进行相关的配置: Cluster Level Shard Allocation用于配置集群中节点如 ...

  10. 解决The file “FWLifeApp” couldn’t be opened because you don’t have permission to view it.问题

    The file “FWLifeApp” couldn’t be opened because you don’t have permission to view it问题是因为项目文件中的Bundl ...