题目描述:
某病毒可以人传人,且传染能力极强,只要与已感染该病毒的人发生接触即刻感染。
现给定一些感染该病毒的人员接触关系,要求你找出其中最早最长的一条传染链。
输入格式:
输入在第一行中给出一个正整数 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 请按任意键继续.