poj 2553(3180) tarjan强连通分量(找图的“sink”点)

本文详细介绍了如何使用Tarjan算法求解图中的强连通分量,并通过两个具体的编程题目实例展示了算法的应用过程。重点讲解了如何利用Tarjan算法解决特定类型的图论问题。

题意:2553:定义图的bottom集合为:bottom(G)={v∈V|∀w∈V:(v→w)⇒(w→v)}。

对于3180,谁能告诉我这个题是什么意思?看了别人的解答是求点数大于等于2的强连通分量的个数,可是为什么呢?

思路:依题意,所求即求出强连通分量缩点后出度为0的那些强连通分量中得点。用tarjan算法即可。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define clr(s,t) memset(s,t,sizeof(s))
#define N 5005
struct edge{
    int y,next;
}e[N*N];
int stack[N],first[N],dfn[N],low[N],instack[N],strong[N];
int n,m,top,id,st,con;
void init(){
    top = id = st = con = 0;
    clr(first,-1);
    clr(dfn,-1);
    clr(instack, 0);
}
int cmp(const void* a,const void* b){
    return (*(int*)a) - (*(int*)b);
}
void add(int x,int y){
    e[top].y = y;
    e[top].next = first[x];
    first[x] = top++;
}
void tarjan(int x){
    int i,y;
    dfn[x] = low[x] = ++id;
    stack[st++] = x;
    instack[x] = 1;
    for(i = first[x];i!=-1;i=e[i].next){
        y = e[i].y;
        if(dfn[y]==-1){
            tarjan(y);
            low[x] = min(low[x],low[y]);
        }else if(instack[y])
            low[x] = min(low[x],dfn[y]);
    }
    if(dfn[x] == low[x]){
        con ++;
        do{
            strong[stack[--st]] = con;
            instack[stack[st]] = 0;
        }while(stack[st] != x);
    }
}
int main(){
    while(scanf("%d",&n) && n){
        int a,b,i,j;
        init();
        scanf("%d",&m);
        for(i = 0;i<m;i++){
            scanf("%d %d",&a,&b);
            add(a,b);
        }
        for(i = 1;i<=n;i++)
            if(dfn[i] == -1)
                tarjan(i);
        
        clr(dfn, 0);
        for(i = 1;i<=n;i++)
            for(j = first[i];j!=-1;j=e[j].next)
                if(strong[i] != strong[e[j].y])
                    dfn[strong[i]] = 1;
        clr(first,0);
        for(top=0,i=1;i<=n;i++)
            if(!dfn[strong[i]])
                first[top++] = i;
        qsort(first,top,sizeof(int),cmp);
        for(i = 0;i<top;i++)
            printf("%d ",first[i]);
        putchar('\n');
    }
    return 0;
}

3180:

#include <stdio.h>
#include <string.h>
#define N 10005
#define INF 0x3fffffff
#define clr(s,t) memset(s,t,sizeof(s))
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
struct edge{
    int y,next;
}e[50005];
int dfn[N],low[N],first[N],stack[N],inst[N];
int n,m,id,top,con,st,res;
void init(){
    top = id = con = st = res = 0;
    clr(first, -1);
    clr(dfn, -1);
    clr(inst, 0);
}
void add(int x,int y){
    e[top].y = y;
    e[top].next = first[x];
    first[x] = top++;
}
void tarjan(int x){
    int i,y,num=0;
    dfn[x] = low[x] = ++id;
    stack[st++] = x;
    inst[x] = 1;
    for(i = first[x];i!=-1;i=e[i].next){
        y = e[i].y;
        if(dfn[y] == -1){
            tarjan(y);
            low[x] = min(low[x], low[y]);
        }else if(inst[y])
            low[x] = min(low[x], dfn[y]);
    }
    
    if(dfn[x] == low[x]){
        con++;
        do{
            --st;
            inst[stack[st]] = 0;
            num++;
        }while(x != stack[st]);
        if(num >= 2)
            res++;
    }
}int main(){
    while(scanf("%d %d",&n,&m) != EOF){
        int i,a,b;
        init();
        for(i = 0;i<m;i++){
            scanf("%d %d",&a,&b);
            add(a,b);
        }
        for(i = 1;i<=n;i++)
            if(dfn[i] == -1)
                tarjan(i);
        printf("%d\n",res);
    }
    return 0;
}


内容概要:本文系统阐述了利用BP神经网络结合Matlab编程实现对水质变化趋势进行科学预测的技术方法。通过构建BP神经网络模型,利用历史水质数据(如pH值、溶解氧、浊度等)进行训练,充分挖掘数据间的非线性关系,实现对未来水质状况的精准预测。该方法在处理复杂、非线性的环境数据方面表现出色,具有较强的泛化能力和实用性,适用于环境监测与水资源管理领域。文中配套提供了完整的Matlab代码实现方案,涵盖数据预处理、模型构建、训练优化及预测分析全过程,便于读者复现与应用。; 适合人群:具备一定机器学习理论基础和Matlab编程能力的科研人员、环境工程及相关专业的高校学生,以及从事水质监测、水污染预警和水资源管理的技术人员。; 使用场景及目标:①用于水质关键参数的时间序列预测,支持水环境长期趋势分析;②为水污染早期预警系统建设、水资源保护政策制定与生态环境治理提供可靠的数据支撑和技术手段;③作为教学实践案例,帮助学习者深入理解神经网络在环境科学中的建模流程与应用逻辑。; 阅读建议:建议读者结合文中提供的Matlab代码逐模块运行与调试,重掌握数据归一化、网络结构设计、训练参数调优及预测结果可视化等关键步骤,同时鼓励将该模型迁移至其他类似时序预测任务中进行拓展验证与性能优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值