图论1E,cf405E

Little Chris is participating in a graph cutting contest. He's a pro. The time has come to test his skills to the fullest.

Chris is given a simple undirected connected graph with n vertices (numbered from 1 to n) and m edges. The problem is to cut it into edge-distinct paths of length 2. Formally, Chris has to partition all edges of the graph into pairs in such a way that the edges in a single pair are adjacent and each edge must be contained in exactly one pair.

For example, the figure shows a way Chris can cut a graph. The first sample test contains the description of this graph.

You are given a chance to compete with Chris. Find a way to cut the given graph or determine that it is impossible!

Input

The first line of input contains two space-separated integers n and m (1 ≤ n, m ≤ 105), the number of vertices and the number of edges in the graph. The next m lines contain the description of the graph's edges. The i-th line contains two space-separated integers ai and bi (1 ≤ ai, bi ≤ nai ≠ bi), the numbers of the vertices connected by the i-th edge. It is guaranteed that the given graph is simple (without self-loops and multi-edges) and connected.

Note: since the size of the input and output could be very large, don't use slow output techniques in your language. For example, do not use input and output streams (cin, cout) in C++.

Output

If it is possible to cut the given graph into edge-distinct paths of length 2, output  lines. In the i-th line print three space-separated integersxiyi and zi, the description of the i-th path. The graph should contain this path, i.e., the graph should contain edges (xi, yi) and (yi, zi). Each edge should appear in exactly one path of length 2. If there are multiple solutions, output any of them.

If it is impossible to cut the given graph, print "No solution" (without quotes).

Sample Input

Input
8 12
1 2
2 3
3 4
4 1
1 3
2 4
3 5
3 6
5 6
6 7
6 8
7 8
Output
1 2 4
1 3 2
1 4 3
5 3 6
5 6 8
6 7 8
Input
3 3
1 2
2 3
3 1
Output
No solution
Input
3 2
1 2
2 3
Output

1 2 3


题意:一个无向图,有你的顶点,m条边,输出m/2条边来,但是要包括所有顶点,输出规则 是,将两条边合并,这两条边有一个顶点是公用顶点,举一个例子:1-2 2-4 ,输出 1-2-4,;

借鉴大神的思路,先宽度搜索,然后深度优先搜索,一直到最低层,如果有落单顶点,那么将该顶点以及上一个顶点以及上上一个顶点输出,否者将上一个顶点加入队列:

这道题真的是不好想,最好看着代码将数据进行模拟一下,不然也是很难理解的

#include <iostream>
#include <queue>
#include <stdio.h>
#include <string.h>
const int maxn=1e6+10;
using namespace std;
struct Edge
{
    int v,next;
}edge[maxn];
int head[maxn];
int tot;
bool vis[maxn];
void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
    memset(vis,false,sizeof(vis));
}
void addedge(int u,int v)
{
    edge[tot].v=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
int bfs(int u)
{
    queue<int>que,que2;///队列2中连续存放的点,挨着的点都是相连的,队列2是主要队列
    for(int i=head[u]; i!=-1; i=edge[i].next)
    {
        if(!vis[i])
        {
            int v=edge[i].v;
            vis[i]=true;
            vis[i^1]=true;
            que.push(v);
        }
    }
    while(!que.empty())
    {
        int mid=que.front();
        que.pop();
        int next=bfs(mid);
        if(next)///如果有落单点输出落单点,上一点,上上一点
            printf("%d %d %d\n",u,mid,next);
        else
            que2.push(mid);
    }
    while(que2.size()>=2)
    {
        int m1=que2.front();
        que2.pop();
        int m2=que2.front();
        que2.pop();
        printf("%d %d %d\n",m1,u,m2);
        cout<<"####"<<endl;
    }
    if(!que2.empty())
        return que2.front();///只返回,不删除队列中大于等于2个时,输出and删除
    else
        return 0;
}
int main()
{
    int m,n,u,v;
    while(scanf("%d%d",&n,&m)!=-1)
    {
        init();
        for(int i=0; i<m; i++)
        {
            scanf("%d%d",&u,&v);
            addedge(u,v);///无向图,双向加边
            addedge(v,u);
        }
        if(m%2==1)///计数个边肯定不行
        {
           printf("No solution\n");
        }
        else
        bfs(1);

    }
    return 0;
}


你可能感兴趣的:(图论1E,cf405E)