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

并查集做法####

维护一个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. BZOJ2300: [HAOI2011]防线修建

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2300 (我只是在发以前写过的题.. 因为题目没说强制在线,所以离线乱搞就可以了.先把点删掉然后 ...

  2. Thinking in Java学习笔记-泛型和类型安全的容器

    示例: public class Apple { private static long counter; private final long id = counter++; public long ...

  3. 微信小程序实现滚动加载更多

    1.需要用到的组件和api scroll-view(可滚动视图区域) wx.showToast(OBJECT)显示消息提示窗----显示loading小菊花用的 2.需要用到的属性 3.scrol-v ...

  4. 人生苦短,我用Python 第一篇

    一.变量名 自定义变量名只能用 数字.字母.下划线组成. 使用变量前,需对其先赋值 注意:1.变量名不能以数字开头:      2.不能是关键字:例如:'and', 'as', 'assert', ' ...

  5. JS和H5做一个音乐播放器,附带源码

    http://mp.weixin.qq.com/s/KpXT9X46AMlUVXQvpHuXGQ 效果图: 实现的功能 1.首页 2.底部播放控件 3.播放页面 4.播放列表 5.排行榜 6.音乐搜索 ...

  6. Python自建logging模块

    本章将介绍Python内建模块:日志模块,更多内容请从参考:Python学习指南 简单使用 最开始,我们用最短的代码体验一下logging的基本功能. import logging logger = ...

  7. Velocity动态拼接字符串

    1.在全局定义一个变量: #set($varName = "") 2.拼接字符串病截取字符串: #foreach( $role in $adminUser.roles) #set( ...

  8. 第二章 在HTML中使用JS

    script 标签 属性 src   : 可选 包含要执行的外部文件 type : 表示编写代码使用的脚本语言的内容类型(MINI类型) text/javascript async: 可选 只对外部脚 ...

  9. impala集成sentry

    1.安装配置sentry 详细步骤见上一篇安装配置sentry. 2.配置impala 注:以下配置未集成kerberos安全认证 在/etc/imapla/conf目录下创建sentry-site. ...

  10. python_print和input

    什么是输入? --用户从键盘.鼠标或其他终端 输入 的数据 -- input("提示信息") --python 2.7 rqw_input("提示信息") 如何 ...