输入

第1行:2个正整数,N,M。表示点的数量N,边的数量M。1≤N≤20,000, 1≤M≤100,000

第2..M+1行:2个正整数,u,v。表示存在一条边(u,v),连接了u,v两台服务器。1≤u<v≤N

保证输入所有点之间至少有一条连通路径。

输出

第1行:若干整数,用空格隔开,表示满足要求的服务器编号。从小到大排列。若没有满足要求的点,该行输出Null

第2..k行:每行2个整数,(u,v)表示满足要求的边,u<v。所有边根据u的大小排序,u小的排在前,当u相同时,v小的排在前面。若没有满足要求的边,则不输出

/* ***********************************************
Author        :devil
Created Time  :2016/6/9 14:8:23
************************************************ */
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <stdlib.h>
using namespace std;
const int N=20010;
int dfn[N],low[N],f[N],cou=1;
vector<int>eg[N];
vector<int>point;
vector<pair<int,int> >edge;
void dfs(int u)
{
    bool add=0;
    int child=0;
    dfn[u]=low[u]=cou++;
    for(int i=0;i<eg[u].size();i++)
    {
        int v=eg[u][i];
        if(v==f[u]) continue;
        if(!dfn[v])
        {
            child++;
            f[v]=u;
            dfs(v);
            low[u]=min(low[u],low[v]);
            if(!add&&((!f[u]&&child>1)||(f[u]&&low[v]>=dfn[u])))
            {
                point.push_back(u);
                add=1;
            }
            if(low[v]>dfn[u]) edge.push_back(make_pair(min(u,v),max(u,v)));
        }
        else low[u]=min(low[u],dfn[v]);
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    int n,m,u,v;
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&u,&v);
        eg[u].push_back(v);
        eg[v].push_back(u);
    }
    dfs(1);
    if(!point.size()) printf("Null\n");
    else
    {
        sort(point.begin(),point.end());
        printf("%d",point[0]);
        for(int i=1;i<point.size();i++)
            printf(" %d",point[i]);
        printf("\n");
    }
    sort(edge.begin(),edge.end());
    for(int i=0;i<edge.size();i++)
        printf("%d %d\n",edge[i].first,edge[i].second);
    return 0;
}