题目链接:http://codeforces.com/problemset/problem/1106/D
题意:给定一张n个点,m条双向边的图,从1号点出发,沿双向边行走(可以重复经过一个点)。当经过一个之前未经过的点时,记录下其编号。这些编号组成一个长度为n的序列。求字典序最小的序列。
思路:
用字典序最小的方法走过图上的所有点,其实就是遍历整张图。因为要满足字典序最小,我们很容易想到Dj算法里面我们用优先队列去维护,使每次都走字典序列最小的。注意本题可以重复走,所以这个算法肯定是正确的
1 #include <iostream>
2 #include <time.h>
3 #include <algorithm>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <cstring>
7 #include <map>
8 #include <queue>
9
10 typedef long long LL;
11
12 using namespace std;
13 const int maxn = 2e5 + 10;
14
15 struct Edge{
16 int to;
17 int next;
18 }edge[maxn];
19
20 int cnt = 0;
21 int head[maxn];
22 int vis[maxn];
23 int ans[maxn];
24 priority_queue<int,vector<int>,greater<int> > q;
25
26 void init(){
27 memset(head,-1, sizeof(head));
28 cnt = 0;
29 }
30
31 void add(int u,int v){
32 edge[cnt].to = v;
33 edge[cnt].next = head[u];
34 head[u] = cnt++;
35 }
36
37 int main(){
38 int n,m;
39 scanf("%d%d",&n,&m);
40 init();
41 for (int i=0;i<m;i++){
42 int u,v;
43 scanf("%d%d",&u,&v);
44 add(u,v);
45 add(v,u);
46 }
47 int tot = 0;
48 q.push(1);
49 while (!q.empty()){
50 int now = q.top();
51 q.pop();
52 if (vis[now])
53 continue;
54 vis[now] = 1;
55 ans[tot++] = now;
56 for (int i=head[now];i!=-1;i=edge[i].next){
57 int v = edge[i].to;
58 if (!vis[v]){
59 q.push(v);
60 }
61 }
62 }
63 for (int i=0;i<tot;i++){
64 printf("%d ",ans[i]);
65 }
66 return 0;
67 }