求有向图的权值为一的最小环##

并查集做法####

维护一个dis[],表示i号元素到fa[i]的距离。

对于输入的每两个点u,v,询问这两个点的fa[]是否相同,如果相同就成环,维护最小值,mi=min(mi,dis[u]+dis[v]+1)。如果不相同,merge(u,v)。目测是最简单的做法。

但是只适用于权值为一的边。

注意对于一条U指向v的边,是将u合并到v上。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN=200005;
int read(){
int rv=0,fh=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') fh=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
rv=(rv<<1)+(rv<<3)+c-'0';
c=getchar();
}
return rv*fh;
}
int fa[MAXN],n,mi=0x7fffffff/3,dis[MAXN];
int find(int x){
if(x!=fa[x]) {
int t=fa[x];fa[x]=find(fa[x]);dis[x]+=dis[t];
}
return fa[x];
}
void merge(int x,int y){
int r1=find(x),r2=find(y);
if(r1!=r2){
fa[r1]=r2;
dis[x]=dis[y]+1;
}
}
int main(){
freopen("in.txt","r",stdin);
n=read();
for(int i=1;i<=n;i++){
fa[i]=i;
}
for(int i=1;i<=n;i++){
int t=read();
if(find(i)==find(t)){
mi=min(mi,dis[i]+dis[t]+1);
}else {
merge(i,t);
}
}
cout<<mi;
fclose(stdin);
return 0;
}

topsort####

使用拓扑排序删掉那些一定不属于环上的点,再用dfs更新最小环的数量。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
const int MAXN=200005;
int read(){
int rv=0,fh=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') fh=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
rv=(rv<<1)+(rv<<3)+c-'0';
c=getchar();
}
return rv*fh;
}
struct edge{
int to,nxt;
}e[MAXN];
int n,head[MAXN],nume,in[MAXN],f[MAXN],mi=0x7fffffff/3,cnt;
void adde(int from,int to){
e[++nume].to=to;
e[nume].nxt=head[from];
head[from]=nume;
}
queue<int> q;
void dfs(int u){
cnt++;
f[u]=1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(!f[v]) dfs(v);
}
}
int main(){
freopen("in.txt","r",stdin);
n=read();
for(int i=1;i<=n;i++){
int t=read();
adde(i,t);
in[t]++;
}
for(int i=1;i<=n;i++){
if(!in[i]){
q.push(i),f[i]=1;
}
}
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
in[v]--;
if(!in[v]&&!f[v]){
q.push(v);f[v]=1;
}
}
}
for(int i=1;i<=n;i++){
cnt=0;
if(!f[i]) {dfs(i);mi=min(mi,cnt);} }
cout<<mi;
fclose(stdin);
return 0;
}

tarjan求强连通分量####

最小环即强连通分量

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
const int MAXN=200005;
int read(){
int rv=0,fh=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') fh=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
rv=(rv<<1)+(rv<<3)+c-'0';
c=getchar();
}
return rv*fh;
}
struct edge{
int to,nxt;
}e[MAXN];
int n,head[MAXN],nume,dfn[MAXN],low[MAXN],in,mi=0x7fffffff/3;
stack <int>s;
bool f[MAXN];
void adde(int from,int to){
e[++nume].to=to;
e[nume].nxt=head[from];
head[from]=nume;
}
void tarjan(int u){
dfn[u]=++in;
low[u]=++in;
f[u]=1;
s.push(u);
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(f[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
int v=0;
int cnt=0;
do{
v=s.top();
s.pop();
f[v]=0;
cnt++;
}while(v!=u);
mi=min(mi,cnt);
// cout<<u<<" "<<cnt<<endl;
}
}
int main(){
freopen("in.txt","r",stdin);
n=read();
for(int i=1;i<=n;i++){
int t=read();
adde(i,t);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) tarjan(i);
}
cout<<mi;
fclose(stdin);
return 0;
}

洛谷 [P2661] 信息传递的更多相关文章

  1. 洛谷P2661 信息传递(最小环,并查集)

    洛谷P2661 信息传递 最小环求解采用并查集求最小环. 只适用于本题的情况.对于新加可以使得两个子树合并的边,总有其中一点为其中一棵子树的根. 复杂度 \(O(n)\) . #include< ...

  2. 洛谷P2661 信息传递==coedevs4511 信息传递 NOIP2015 day1 T2

    P2661 信息传递 题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知 ...

  3. 洛谷 P2661 信息传递 题解

    P2661 信息传递 题目描述 有 \(n\) 个同学(编号为 \(1\) 到 \(n\) )正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为 \(i\) 的同学的信息传 ...

  4. 洛谷 P2661 信息传递(并查集 & 最小环)

    嗯... 题目链接:https://www.luogu.org/problemnew/show/P2661 这道题和一些比较水的并查集不太一样,这道题的思路就是用并查集来求最小环... 首先,如果我们 ...

  5. [NOIP2015] 提高组 洛谷P2661 信息传递

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  6. 洛谷 P2661 信息传递 Label:并查集||强联通分量

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  7. NOIP2015提高组T2 洛谷P2661 信息传递

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  8. 洛谷——P2661 信息传递

    https://www.luogu.org/problem/show?pid=2661#sub 题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其 ...

  9. 洛谷p2661信息传递题解

    题目 这个题一眼看上去就是用并查集求最小环. 我们可以设两个数组分别是f,d分别表示该点的爸爸和该点到祖先的距离. 当该点的爸爸等于他时,那他肯定就是祖先. 此时信息就肯定传递完了,此时的整个图中(我 ...

  10. 洛谷P2661信息传递

    传送门啦 一个人要想知道自己的生日,就意味着信息的传递是成环的,因为每轮信息只能传递一个人,传递的轮数就等于环的大小 环的大小就等于环中的两个点到第三个点的距离之和加一,我们就可以在使用并查集时,维护 ...

随机推荐

  1. hdu_1573 X问题(不互素的中国剩余定理)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1573 X问题 Time Limit: 1000/1000 MS (Java/Others)    Me ...

  2. Logger之Logger.getLogger(CLass)技巧代替system.out.print

    ---恢复内容开始--- 尊重原创:http://www.cnblogs.com/zxf330301/p/5876117.html 之前一直在使用System.out.println()来调试.但是用 ...

  3. PHP error_reporting() 错误控制函数功能详解

    定义和用法: error_reporting() 设置 PHP 的报错级别并返回当前级别.   函数语法: error_reporting(report_level)   如果参数 level 未指定 ...

  4. :nth-child(n)

    规定属于其父元素的第二个子元素的每个 p 的背景色: p:nth-child(2) { background:#ff0000; } 1定义和用法 :nth-child(n) 选择器匹配属于其父元素的第 ...

  5. 免费空间上的mysql数据库怎么连接?

    我申请了一个php的免费空间,空间有带mysql数据库,可是我不知道怎么连接. 平时在本地做php时我都是怎么连接的 可是现在到空间上了我就不知道怎么连接了.空间有提供phpmyadmin 会的教一下 ...

  6. dedecms中{dede:myad name='about'/} 修改内容

    网站首页index.htm中调用这个命令,显示一段文字,但是想要修改内容.所以想知道这个命令指定的文件内容在哪里寻找或者指定内容在哪里修改? 匿名 | 浏览 6036 次 发布于2014-02-19 ...

  7. IT术语的正确读法

    Linux /ˈlɪnəks/ /ˈlɪnʊks/(EU) Linux 是一类 Unix 计算机操作系统的统称.该操作系统的核心的名字也是“ Linux” .参考: < !-- m --> ...

  8. AI_神经网络监督学习

    神经网络的神奇之处在哪? 所有神经网络创造出来的价值,都是由一种机器学习,称之为监督学习, 下面这些例子神经网络效果拔群,通过深度学习获利最多的是在线广告 技术的进步来源于计算机视觉和深度学习 例如: ...

  9. mydate97设置时间

    1.引入包 2.页面引入 <script type="text/javascript" src="${pageContext.request.contextPath ...

  10. maven系列--maven常用命令

    下一篇博客我会讲解用eclipse的m2插件来使用maven,这里先大概的了解下maven常用的命令.之后我在详细整理maven的生命周期,到时候会细致的讲解下这些指令应该要怎么使,maven都帮我们 ...