cf22C (构造带割点的图)

Description

Bob got a job as a system administrator in X corporation. His first task was to connect n servers with the help of m two-way direct connection so that it becomes possible to transmit data from one server to any other server via these connections. Each direct connection has to link two different servers, each pair of servers should have at most one direct connection. Y corporation, a business rival of X corporation, made Bob an offer that he couldn't refuse: Bob was asked to connect the servers in such a way, that when server with indexv fails, the transmission of data between some other two servers becomes impossible, i.e. the system stops being connected. Help Bob connect the servers.

Input

The first input line contains 3 space-separated integer numbers nmv (3 ≤ n ≤ 105, 0 ≤ m ≤ 105, 1 ≤ v ≤ n), n — amount of servers, m — amount of direct connections, v — index of the server that fails and leads to the failure of the whole system.

Output

If it is impossible to connect the servers in the required way, output -1. Otherwise output m lines with 2 numbers each — description of all the direct connections in the system. Each direct connection is described by two numbers — indexes of two servers, linked by this direct connection. The servers are numbered from 1. If the answer is not unique, output any.

Sample Input

Input
5 6 3
Output
1 2
2 3
3 4
4 5
1 3
3 5
Input
6 100 1
Output
-1

题意:输入n,m,v表示n个点,m条边,其中v是割点,问能否构造出这样一个图,如果能就输出所有的双向边。

思路:首先这m条边肯定是有上下限的,显然m条边的下限是图的最少边数——树,所以m>=n-1。然后求上限,因为有一个割点,我们把这个割点独立出来,要使边数最多,剩下的部分一定形成了两大部分且这两部分每个部分都是完全图,我们假设这两部分一部分点个数是x,另一部分是y,那么显然x+y=n-1,由于是完全图,x部分的所有边是x*(x-1)/2,y部分的所有边是y*(y-1)/2,再加上这两部分的所有点都要跟v相连,那么我们所求的边数

m<=x*(x-1)/2+y*(y-1)/2+x+y

=(x*x+y*y+2*x*y-2*x*y-x-y+2*x+2*y)/2

=((x+y)^2+x+y-2*x*y)/2

=((x+y)*(x+y+1)-2*x*y)/2

=(n*(n-1)-2*x*y)/2(带入x+y=n-1)

现在要求上式 的最大值,由于n已知,也就是求-2*x*y的最大值,也就是求x*y的最小值。由高中学过的不等式可知当x+y和一定的时候,x和y越接近,x*y越大,x和y差越大,x*y越小,由于x>=1,y>=1.所以我们取一个为1,另一个为n-2,得到上式变成了:

m<=(n*n-n-2*(n-2))/2

=(n*n-3*n+4)/2

即为所求的上限。

然后最终的处理就是和求上限的方法类似,用单独一个点只和割点连边,割点和每个点都连边,其他只要满足m尽情的连边即可。


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
using namespace std;
typedef long long ll;

int main()
{
    int n,m,v;
    scanf("%d%d%d",&n,&m,&v);
    if(m<n-1||m>(n*n-3*n+4)/2)
        puts("-1");
    else
    {
        for(int i=1; i<=n; i++)
            if(i!=v)
                printf("%d %d\n",v,i);
        m-=n-1;
        int dan=1;
        if(v==1)
            dan=2;
        for(int i=1; i<=n&&m; i++)
            if(i!=v&&i!=dan)
                for(int j=i+1; j<=n&&m; j++)
                    if(j!=v&&j!=dan)
                        printf("%d %d\n",i,j),m--;
    }
    return 0;
}


posted @ 2016-05-05 11:31  martinue  阅读(188)  评论(0编辑  收藏  举报