2015Day1T2信息传递

本文介绍了几种求解图中最小环的方法,包括深度优先搜索(DFS)、并查集及Tarjan算法。通过具体实例展示了不同算法的应用场景和技术细节,为读者提供了一种高效解决实际问题的途径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里写图片描述
bfs和dfs

//求最小环 
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,u,y,cnt,mn=0x3fffffff,c,t,p;
int head[200005],col[200005],st[200005];
int bc[200005],b[200005],cn[200005];
//col每个连通块的颜色,st记录每个连通块
//b是否已经记录过,如果是,表示已经构成环了
//cn记录队列的编号,与环的第一个点相减表示该环的个数 
struct Data{
    int to,nxt;
};
Data edge[400005]; 
void add(int u,int v)
{
    cnt++;
    edge[cnt].to=v;//edge[2].nxt
    edge[cnt].nxt=head[u];
    head[u]=cnt;
} 
int dfs(int u,int c)
{
    for(int i=head[u];i>0;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(col[v]==0)
        {
            col[v]=c;
            dfs(v,c);
        }
    }
}
int dfs2(int u)
{
    int v=bc[u];//u的后继 
    p++;
    if(b[v]==1)
        return p-cn[v]; 
    cn[v]=p;
    b[v]=1;
    dfs2(v);
}
int main()
{
    scanf("%d",&n);
    for(int x=1;x<=n;x++)
    {
        scanf("%d",&y);
        add(x,y); 
        add(y,x);//设置成无向的 
        bc[x]=y;
    }
//  for(int i=1;i<=n;i++)
//  {
//      for(int j=hd[i];j>0;j=eg[j].nxt)
//          cout<<i<<","<<eg[j].to<<endl;
//  }
    for(int i=1;i<=n;i++)
    {
        if(col[i]==0)
        {
            c++;
            col[i]=c;
            st[++t]=i;//记录一共几个连通块 
            dfs(i,c);//将能设涉及到的都涉及 
        }
    }
//  for(int i=1;i<=t;i++)
//      cout<<i<<","<<st[i]<<endl;
    for(int i=1;i<=t;i++)
    {
        memset(cn,0,sizeof cn);
        b[st[i]]=1;p=0;
        int tmp=dfs2(st[i]);
        if(tmp<mn)
            mn=tmp;
    } 
    printf("%d\n",mn);
}
/*
9
2 4 2 3 1 7 8 6 6

output:
3 3
*/

并查集

//求最小环 
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,u,y,cnt,mn=0x3fffffff,c,t,p;
int fa[200005],st[200005],jud[200005];
int bc[200005],b[200005],cn[200005];
//col每个连通块的颜色,st记录每个连通块
//b是否已经记录过,如果是,表示已经构成环了
//cn记录队列的编号,与环的第一个点相减表示该环的个数 
int find(int x)
{
    if(x==fa[x]) return x;
    find(fa[x]);
}
void uni(int p,int q)
{
    fa[q]=p;
}
int dfs2(int u)
{
    int v=bc[u];//u的后继 
    p++;
    if(b[v]==1)
        return p-cn[v]; 
    cn[v]=p;
    b[v]=1;
    dfs2(v);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        fa[i]=i;//每个点的父节点是自己 
    int g,h;
    for(int x=1;x<=n;x++)
    {
        scanf("%d",&y);
        bc[x]=y;
        g=find(x),h=find(y);
        if(g!=h)
            uni(g,h);//把两个父亲fa[h]=g进行合并 
    }
    for(int i=1;i<=n;i++)
    {
        int f=find(i);
        if(jud[f]==0) jud[f]=1,st[++t]=f;   
    }
//  for(int i=1;i<=t;i++)
//      cout<<i<<","<<st[i]<<endl;
    for(int i=1;i<=t;i++)
    {
        memset(cn,0,sizeof cn);
        b[st[i]]=1;p=0;
        int tmp=dfs2(st[i]);
        if(tmp<mn)
            mn=tmp;
    } 
    printf("%d\n",mn);
}
/*
9
2 4 2 3 1 7 8 6 6
*/

并查集-路径压缩

//求最小环 
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,u,y,cnt,mn=0x3fffffff,c,t,p;
int fa[200005],st[200005],jud[200005];
int bc[200005],b[200005],cn[200005];
//col每个连通块的颜色,st记录每个连通块
//b是否已经记录过,如果是,表示已经构成环了
//cn记录队列的编号,与环的第一个点相减表示该环的个数 
int find(int x)
{
    if(x!=fa[x]) fa[x]=find(fa[x]);
    else return x;
}
void uni(int p,int q)
{
    fa[q]=p;
}
int dfs2(int u)
{
    int v=bc[u];//u的后继 
    p++;
    if(b[v]==1)
        return p-cn[v]; 
    cn[v]=p;
    b[v]=1;
    dfs2(v);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        fa[i]=i;//每个点的父节点是自己 
    int g,h;
    for(int x=1;x<=n;x++)
    {
        scanf("%d",&y);
        bc[x]=y;
        g=find(x),h=find(y);
        if(g!=h)
            uni(g,h);//把两个父亲fa[h]=g进行合并 
    }
//  for(int i=1;i<=n;i++)
//      cout<<i<<","<<fa[i]<<endl;//并不是所有点的fa[]都更新了,只是在find过程中路径上的点被更新了 

    for(int i=1;i<=n;i++)
    {
        int f=find(i);
        if(jud[f]==0) jud[f]=1,st[++t]=f;   
    }
    for(int i=1;i<=t;i++)
        cout<<i<<","<<st[i]<<endl;
    for(int i=1;i<=t;i++)
    {
        memset(cn,0,sizeof cn);
        b[st[i]]=1;p=0;
        int tmp=dfs2(st[i]);
        if(tmp<mn)
            mn=tmp;
    } 
    printf("%d\n",mn);
}
/*
9
2 4 2 3 1 7 8 6 6
*/

tarjan

//求最小环 
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,x,y,tp,tim,mn;
int ans=0x3fffffff; 
int dfn[200005],low[200005],insk[200005],bc[200005],stk[200005];
//st记录每个连通块
//b是否已经记录过,如果是,表示已经构成环了
//cn记录队列的编号,与环的第一个点相减表示该环的个数
void tarjan(int u)
{
    dfn[u]=low[u]=++tim;
    insk[u]=1;
    stk[++tp]=u;
    int v=bc[u];
    if(!dfn[v])
    {
        tarjan(v);
        low[u]=min(low[u],low[v]);
    }
    else if(insk[v]==1)
    {
        low[u]=min(low[u],low[v]);
    }
    if(low[u]==dfn[u])
    {
        while(1)
        {
            mn++;
            int now=stk[tp];
            tp--;
            if(now==u) break;
        }
        if(mn>1)
            ans=min(ans,mn);
    }
} 
int main()
{
    scanf("%d",&n);
    for(int x=1;x<=n;x++)
    {
        scanf("%d",&y);
        bc[x]=y;
    } 
    for(int i=1;i<=n;i++)
    {
//        memset(dfn,0,sizeof dfn);
//        memset(low,0,sizeof low);
//        tim=0;
        mn=0;
        if(!dfn[i])
            tarjan(i);  
    } 
    cout<<ans<<endl;
} 
资源下载链接为: https://pan.quark.cn/s/1bfadf00ae14 “STC单片机电压测量”是一个以STC系列单片机为基础的电压检测应用案例,它涵盖了硬件电路设计、软件编程以及数据处理等核心知识点。STC单片机凭借其低功耗、高性价比和丰富的I/O接口,在电子工程领域得到了广泛应用。 STC是Specialized Technology Corporation的缩写,该公司的单片机基于8051内核,具备内部振荡器、高速运算能力、ISP(在系统编程)和IAP(在应用编程)功能,非常适合用于各种嵌入式控制系统。 在源代码方面,“浅雪”风格的代码通常简洁易懂,非常适合初学者学习。其中,“main.c”文件是程序的入口,包含了电压测量的核心逻辑;“STARTUP.A51”是启动代码,负责初始化单片机的硬件环境;“电压测量_uvopt.bak”和“电压测量_uvproj.bak”可能是Keil编译器的配置文件备份,用于设置编译选项和项目配置。 对于3S锂电池电压测量,3S锂电池由三节锂离子电池串联而成,标称电压为11.1V。测量时要考虑电池的串联特性,通过分压电路将高电压转换为单片机可接受的范围,并实时监控,防止过充或过放,以确保电池的安全和寿命。 在电压测量电路设计中,“电压测量.lnp”文件可能包含电路布局信息,而“.hex”文件是编译后的机器码,用于烧录到单片机中。电路中通常会使用ADC(模拟数字转换器)将模拟电压信号转换为数字信号供单片机处理。 在软件编程方面,“StringData.h”文件可能包含程序中使用的字符串常量和数据结构定义。处理电压数据时,可能涉及浮点数运算,要了解STC单片机对浮点数的支持情况,以及如何高效地存储和显示电压值。 用户界面方面,“电压测量.uvgui.kidd”可能是用户界面的配置文件,用于显示测量结果。在嵌入式系统中,用
资源下载链接为: https://pan.quark.cn/s/abbae039bf2a 在 Android 开发中,Fragment 是界面的一个模块化组件,可用于在 Activity 中灵活地添加、删除或替换。将 ListView 集成到 Fragment 中,能够实现数据的动态加载与列表形式展示,对于构建复杂且交互丰富的界面非常有帮助。本文将详细介绍如何在 Fragment 中使用 ListView。 首先,要在 Fragment 的布局文件中添加 ListView 的 XML 定义。一个基本的 ListView 元素代码如下: 接着,创建适配器来填充 ListView 的数据。通常会使用 BaseAdapter 的子类,如 ArrayAdapter 或自定义适配器。例如,创建一个简单的 MyListAdapter,继承自 ArrayAdapter,并在构造函数中传入数据集: 在 Fragment 的 onCreateView 或 onActivityCreated 方法中,实例化 ListView 和适配器,并将适配器设置到 ListView 上: 为了提升用户体验,可以为 ListView 设置点击事件监听器: 性能优化也是关键。设置 ListView 的 android:cacheColorHint 属性可提升滚动流畅度。在 getView 方法中复用 convertView,可减少视图创建,提升性能。对于复杂求,如异步加载数据,可使用 LoaderManager 和 CursorLoader,这能更好地管理数据加载,避免内存泄漏,支持数据变更时自动刷新。 总结来说,Fragment 中的 ListView 使用涉及布局设计、适配器创建与定制、数据绑定及事件监听。掌握这些步骤,可构建功能强大的应用。实际开发中,还优化 ListView 性能,确保应用流畅运
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值