Codeforces 330E Graph Reconstruction【随机化算法】Get it!

E. Graph Reconstruction
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

I have an undirected graph consisting of n nodes, numbered 1 through n. Each node has at most two incident edges. For each pair of nodes, there is at most an edge connecting them. No edge connects a node to itself.

I would like to create a new graph in such a way that:

  • The new graph consists of the same number of nodes and edges as the old graph.
  • The properties in the first paragraph still hold.
  • For each two nodes u and v, if there is an edge connecting them in the old graph, there is no edge connecting them in the new graph.

Help me construct the new graph, or tell me if it is impossible.

Input

The first line consists of two space-separated integers: n and m (1 ≤ m ≤ n ≤ 105), denoting the number of nodes and edges, respectively. Then m lines follow. Each of the m lines consists of two space-separated integers u and v (1 ≤ u, v ≤ nu ≠ v), denoting an edge between nodes u and v.

Output

If it is not possible to construct a new graph with the mentioned properties, output a single line consisting of -1. Otherwise, output exactly m lines. Each line should contain a description of edge in the same way as used in the input format.

Examples
Input
8 7
1 2
2 3
4 5
5 6
6 8
8 7
7 4
Output
1 4
4 6
1 6
2 7
7 5
8 5
2 8
Input
3 2
1 2
2 3
Output
-1
Input
5 4
1 2
2 3
3 4
4 1
Output
1 3
3 5
5 2
2 4
Note

The old graph of the first example:

A possible new graph for the first example:

In the second example, we cannot create any new graph.

The old graph of the third example:

A possible new graph for the third example:


题目大意:


给你一个图,有N个点,M条无向边,现在要求你建立出来一个新图,使得也是N个点M条无向边,并且需要保证每个点的度小于等于2(同时保证原图的度也小于等于2),并且要求旧图中有的边,新图中不能有。

如果一个点孤立出去了,相当于有一条边(u,u);

如果存在解,输出任意一个,否则输出-1.


思路:


初入门随机化算法,我们有N个点,最多N条边,那么我们随机这N个点的排列成一行,ans【i】和ans【i+1】建边,因为最多有N条边,所以我们再将ans【n】和ans【1】建边,构成一个环。


然后将其中的边进行判定,如果出现在原图了,这条边就不能建,否则就可以建,看看每一次随机出来的结果是否能够达到m条边,如果可以建立出m条边,就是一个可行的做法。


我们每一次随机完之后,如果有n个点,那么对于原图中假设存在有一个点a,其度为2.那么随机之后这个点能够连出一条边的概率是n-2/n。

所以随机化做法是完全可行的,一共有N*(N-1)/2条边,避免一个点接触到相邻两个点的概率是非常大的。


判重边用map标记一下就行。


Ac代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
using namespace std;
map<pair<int,int>,int>s;
int ans[100004];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        s.clear();
        for(int i=0;i<m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            s[make_pair(x,y)]=1;
            s[make_pair(y,x)]=1;
        }
        for(int i=1;i<=n;i++)
        {
            s[make_pair(i,i)]=1;
        }
        int flag=0;
        for(int i=1;i<=n;i++)ans[i]=i;
        int t=500;
        while(t--)
        {
            random_shuffle(ans+1,ans+1+n);
            ans[0]=ans[n];
            int cnt=0;
            for(int i=0;i<n;i++)
            {
                if(s[make_pair(ans[i],ans[i+1])]==1)continue;
                else cnt++;
            }
            if(cnt<m)continue;
            flag=1;
            for(int i=0;i<n;i++)
            {
                if(s[make_pair(ans[i],ans[i+1])]==1)continue;
                if(m>0)
                {
                    m--;
                    printf("%d %d\n",ans[i],ans[i+1]);
                }
            }
            break;
        }
        if(flag==0)printf("-1\n");
    }
}















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值