【数据结构与算法实习】题目8 传染链( Infectious Chain )

题目描述:
某病毒可以人传人,且传染能力极强,只要与已感染该病毒的人发生接触即刻感染。
现给定一些感染该病毒的人员接触关系,要求你找出其中最早最长的一条传染链。

输入格式:
输入在第一行中给出一个正整数 N(N≤10^4),即感染病毒的人员总数,从 0 到 N−1 进行编号。
随后N 行按照编号顺序给出人员接触信息,每行按以下格式描述该人员的接触对象:
k 接触人员1 …… 接触人员k
其中 k 是该编号人员接触的其他人总数,后面按照时间先后给出所有接触的人员编号。题目保证传染源头有且仅有一个,且已被感染人员不会与另一个感染人员再接触。

输出格式:
第一行输出从源头开始的最早最长传染链长度。
第二行输出从源头开始的最早最长传染链,编号之间以1个空格分隔,行首尾不得有多余空格。这里的最早最长传染链是指从源头开始的传染链上的人数最多,且被感染的时间最早。
所谓时间最早指的两个长度相等的传染链{a1,a2,…,an}和{b1,b2,…,bn},存在1≤k<n,对于所有的i (1≤i<k)都满足ai=bi,且ak被感染的时间早于bk被感染的时间。

输入样例:

10
0
3 3 4 7
2 1 9
1 6
1 5
0
0
0
2 6 0
1 8

输出样例:

4
2 1 3 6

题解:

//本题的逻辑结构:图
//本题的存储结构:顺序
//解题思路和算法:获取入度的数组,从入度为0的某一点开始深度优先遍历,获取能够达到的最大深度即为最长传染链长度,
//              之后获取传染链的位数,依次获取三个数组
//              数组1:当前的序号;数组2:最大深度;数组3:每访问一个节点的当前深度
                // 比如测试数据3的对应数组
                //  数组1:0 1 3 5 2 4
                // 数组2:0 1 2 3 3 3
                //数组3:0 1 2 3 1 2 
                // 获取数组2的第一次达到的最大值和最大值的下标,进而从当前位置向左访问数组3中(最大值-1)的下标,
                // 进而从当前位置向左访问数组3中(最大值-2)的下标,直到访问数组3中值0的下标,通过上述下标的反序访问数组1即为
                // 待输出的最长传染链序列
//效率:时间复杂度O(n^2)、空间复杂度O(1):
//测试数据: (1)输入:// 5
                    // 0
                    // 1 2
                    // 1 3
                    // 1 4
                    // 1 0
                // 输出:5
                // 1 2 3 4 0 
        // (2)输入:(涉及时间先后)
                    // 6
                    // 2 1 2
                    // 1 3
                    // 1 4
                    // 1 5
                    // 0
                    // 0 
                // 输出:4
                    // 0 1 3 5
        //  (3)输入: 6
                    // 2 1 2
                    // 1 3
                    // 1 4
                    // 1 5
                    // 0
                    // 0
                // 输出:4
                    // 0 1 3 5

#include<stdio.h>
#include<stdio.h>
#include<malloc.h>
#define max(a,b) ((a)>(b)?(a):(b))

#define MaxVertexNum 1000
#define INFINITY 0
typedef int Vertex;
typedef int DataType;

typedef struct GNode * PtrToGNode;
struct GNode
{
    /* data */
    int Nv;
    int Ne;
    DataType G[MaxVertexNum][MaxVertexNum];
};
typedef PtrToGNode MGraph;

typedef struct ENode * PtrToENode;
struct ENode
{
    /* data */
    Vertex V1, V2;
};
typedef PtrToENode Edge;

MGraph CreateGraph(int VertexNum){
    Vertex V, W;
    MGraph Graph;

    Graph = (MGraph) malloc (sizeof(struct GNode));
    Graph->Nv = VertexNum;
    Graph->Ne = 0;

    for(V = 0; V < Graph->Nv; V++){
        for(W = 0; W < Graph->Nv; W++){
            Graph->G[V][W] = INFINITY;
        }
    }
    return Graph;
}

void InsertEdge(MGraph Graph, Edge E){
    Graph->G[E->V1][E->V2] = 1;
    Graph->Ne++;
}

MGraph BuildGraph(){
    MGraph Graph;
    Edge E;
    Vertex V;
    int Nv, i;
    int eNum;

    scanf("%d", &Nv);
    Graph = CreateGraph(Nv);
    Graph->Ne = 0;
    for(int i=0;i<Graph->Nv;i++){
        scanf("%d",&eNum);
        for(int j=0;j<eNum;j++){
            E = (Edge)malloc(sizeof(struct ENode));
            E->V1 = i;
            scanf("%d",&E->V2);
            InsertEdge(Graph, E);
        }
    }
    return Graph;
}

int Recordx[MaxVertexNum];
int RecordMaxNum[MaxVertexNum];
int RecordNum[MaxVertexNum];
int RecordCount = 0;
int maxNum = 0;
int findN(MGraph G1, int x, int num){
    if(maxNum<num){
        maxNum = max(maxNum, num);
    }
    Recordx[RecordCount]=x;
    RecordMaxNum[RecordCount]=maxNum;
    RecordNum[RecordCount]=num;
    RecordCount++;
    int count = 0;
    for(int i=0;i<G1->Nv;i++){
        if(G1->G[x][i]){
            num = findN(G1, i, ++num);
            count++;
        }
    }
    // if(maxNum<num){
    //     maxNum = max(maxNum, num);
    // }
    return --num;
}

int main(){
    MGraph G1 = BuildGraph();
    // for(int i = 0; i<G1->Nv;i++){
    //     for(int j=0;j<G1->Nv;j++){
    //         printf("%d ", G1->G[i][j]);
    //     }
    //     printf("\n");
    // }
    // printf("\n");
    int Arr[G1->Nv];
    int find0 = 0;
    for(int i = 0; i<G1->Nv;i++){
        for(int j=0;j<G1->Nv;j++){
            find0 += G1->G[j][i];
        }
        Arr[i] = find0;
        find0 = 0;
    }
    int findRD0=0;
    for(findRD0=0;findRD0<10;findRD0++){
        // printf("%d ", Arr[i]);
        if(Arr[findRD0]==0)
            break;
    }
    findN(G1, findRD0, 0);
    printf("%d\n", maxNum+1);
    // for(int i=0;i<RecordCount;i++){
    //     printf("%d ", Recordx[i]);
    //     // if(i<maxNum)
    //     //     printf(" ");
    // }
    // printf("\n");
    // for(int i=0;i<RecordCount;i++){
    //     printf("%d ", RecordMaxNum[i]);
    // }
    // printf("\n");
    // for(int i=0;i<RecordCount;i++){
    //     printf("%d ", RecordNum[i]);
    // }
    int resArr[MaxVertexNum];

    int maxValue =0;
    int maxValuePos = 0;
    for(int i=0;i<RecordCount;i++){
        if(maxValue<RecordMaxNum[i]){
            maxValuePos = i;
        }
        maxValue = max(maxValue, RecordMaxNum[i]);
    }
    for(int i=0;i<maxValue+1;i++){
        resArr[i]=Recordx[maxValuePos];//最大值添加到结果集
        for(int j=maxValuePos-1;j>=0;j--){//循环
            if(RecordNum[j]==RecordNum[maxValuePos]-1)//当层数小一
                maxValuePos = j;//层数对应位置重置
            break;//结束循环
        }
    }

    for(int i=maxValue;i>=0;i--){
        printf("%d", resArr[i]);
        if(i>0){
            printf(" ");
        }
    }

    return 0;
}

// 5
// 0
// 1 2
// 1 3
// 1 4
// 1 0

// 涉及时间先后:
// 6
// 2 1 2
// 1 3
// 1 4
// 1 5
// 0
// 0 

// 6
// 2 1 2
// 1 3
// 1 4
// 1 5
// 0
// 0
// 4
// 0 1 3 5 2 4
// 0 1 2 3 3 3
// 0 1 2 3 1 2 请按任意键继续.
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
传染病模型: 传染病模型是一种用来研究传染病在人群中传播的数学模型。其中最常见的模型包括SIR模型、SEIR模型等。 SIR模型基本原理: SIR模型是一种基于人口流动的传染病模型,它将人口分为三类:易感者(Susceptible)、感染者(Infectious)和康复者(Recovered)。在该模型中,假设康复者获得免疫力,易感者和感染者之间通过接触进行传播。传播速率由感染者的传染能力和易感者的数量共同决定。SIR模型的基本假设是人口数量不变,即不存在出生和死亡。 SIR模型表述: 假设总人口为N,易感者人数为S,感染者人数为I,康复者人数为R。则有以下方程组: dS/dt = -βSI // 易感者被感染的速率 dI/dt = βSI - γI // 感染者康复的速率 dR/dt = γI // 康复者增加的速率 其中,β表示感染率,γ表示恢复率。SIR模型的基本思想是,感染者通过接触易感者传染病毒,易感者通过感染者康复变为康复者,康复者拥有免疫力,不再感染。 战争模型: 战争模型是一种用于研究战争决策的数学模型。其中最常见的模型包括Lanchester战争模型、Lotka-Volterra战争模型等。 Lanchester战争模型基本原理: Lanchester战争模型是经典的战争模型之一,它假设战斗双方的战斗力与其军队的数量成正比。在该模型中,假设战斗双方分别为A和B,其战斗力分别为a和b,其军队数量分别为NA和NB。假设每个人的战斗力相同,则总战斗力分别为aNA和bNB。战斗双方在战斗中相互消耗,直到一方的军队数量降为零,另一方获得胜利。 Lanchester战争模型表述: 假设战斗双方A和B的初始兵力分别为NA和NB,则有以下方程组: dNA/dt = -bNB // A军队损失速率 dNB/dt = -aNA // B军队损失速率 其中,a和b分别为A和B的单位战斗力,即每个人的战斗力,它们的大小可以反映出军队的技术水平、装备水平等因素。Lanchester战争模型的基本思想是,战斗双方在战斗中相互消耗,直到一方的军队数量降为零,另一方获得胜利。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

a9c93f2300

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值