第五次解题报告
第一题 图的深度优先搜索I
-
题目描述
无向图 G 有 n 个顶点和 m 条边。求图G的深度优先搜索树(森林)以及每个顶点的发现时间和完成时间。每个连通分量从编号最小的结点开始搜索,邻接顶点选择顺序遵循边的输入顺序。
在搜索过程中,第一次遇到一个结点,称该结点被发现;一个结点的所有邻接结点都搜索完,该结点的搜索被完成。深度优先搜索维护一个时钟,时钟从0开始计数,结点被搜索发现或完成时,时钟计数增1,然后为当前结点盖上时间戳。一个结点被搜索发现
和完成的时间戳分别称为该结点的发现时间和完成时间。
输入格式:
第1行,2个整数n和m,用空格分隔,分别表示顶点数和边数, 1≤n≤50000, 1≤m≤100000.
第2到m+1行,每行两个整数u和v,用空格分隔,表示顶点u到顶点v有一条边,u和v是顶点编号,1≤u,v≤n.
输出格式:
第1到n行,每行两个整数di和fi,用空格分隔,表示第i个顶点的发现时间和完成时间1≤i≤n 。
第n+1行,1个整数 k ,表示图的深度优先搜索树(森林)的边数。
第n+2到n+k+1行,每行两个整数u和v,表示深度优先搜索树(森林)的一条边<u,v>,边的输出顺序按 v 结点编号从小到大。
输入样例:
在这里给出一组输入。例如:
6 5
1 3
1 2
2 3
4 5
5 6
输出样例:
在这里给出相应的输出。例如:
1 6
3 4
2 5
7 12
8 11
9 10
4
3 2
1 3
4 5
5 6
-
题目分析
审题可知,题目要求的两个时间戳应分别加在每个结点完成DFS之前和之后。由于时间单调增加且为所有结点公用,故其只能作为全局变量。
在DFS之前将即将进行DFS的边存入一个数组,就得到图的深度优先搜索树的所有边。将其排序即可。
保存边的同时进行计数即可得到深度优先搜索树的边数。
-
算法实现
#include<bits/stdc++.h>
using namespace std;
const int MAXN=100010;
vector<int> graph[MAXN>>1];
int visited[MAXN];
int time1[MAXN];
int time2[MAXN];
int edge1[MAXN];
int edge2[MAXN];
int n,m;
int k=0;
int time0=0;
void insert_sort(int a,int b)//插入排序,将新元素插入已经排好的序列中
{
int j;
for(j=k-1;j>=0&&(b<edge2[j]||edge2[j]==0);j--)
{
edge2[j+1]=edge2[j];
edge1[j+1]=edge1[j];
}
edge1[j+1]=a;
edge2[j+1]=b;
}
void DFS(int index)
{
visited[index]=1;
time0++;
time1[index]=time0; //时间戳1
for(int i=1;i<graph[index].size();i++)
{
if(visited[graph[index][i]]!=1)
{
insert_sort(index,graph[index][i]); //保存边
k++; //对边进行计数
DFS(graph[index][i]);
}
}
time0++;
time2[index]=time0; //时间戳2
}
int main()
{
scanf("%d%d",&n,&m);