cf22C (构造带割点的图)

202 篇文章 0 订阅
123 篇文章 0 订阅

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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值