现在的位置: 首页 > 综合 > 正文

CodeForces 22C System Administrator (贪心)

2018年01月14日 ⁄ 综合 ⁄ 共 1025字 ⁄ 字号 评论关闭

题目类型  贪心题


题目意思
给出 3 个数 n, m, v ( 3 <= n <= 1e5, 0 <= m <= 1e5, 1 <= v <= n)
n -> 表示有 n 个点
m -> 表示有 m 条边(无向边)
v -> 表示要删除的点
现在你要在 n 个点上构造 m 条边出来 (注意两点之间只能构造一条无向边, 即没有重边), 这 m 条边构造出来后 n 个点之间要相互可达(即你构造出来的是一个连通图)
然后要求当把点 v 从 n 个点删除后(当然这时候与 v 相连的边也删除了) 剩下的图是不连通的(即某个点没有路通向某个点)

解题方法
首先我们要保证构造出来的 m 条边可以构造出一个连通图, 即 m >= (n-1)
然后可以看到, 既然最终要求剩下的点不连通, 那么我们只要孤立一个点就行了
例如可以这样 -> 孤立的点 u = (v == n ? n-1 : n); 意思是如果 v == n的话我们就孤立 n-1否则就孤立 n
这时可以发现 我们最多可以添加的边数是  除了 u 还有 n-1个点, 每个点向其他的 n-2个点连一条边的话 即有 (n-1)*(n-2)/2 条边(无向边,所以要除2) 然后构造出来的图要连通所以 v -> u要连一条边, 所以 m 最大是 (n-1)*(n-2)/2+1
即如果  (n-1) <= m <= (n-1)*(n-2)/2+1 ,则有解,且很容易就可以构造出来(详见代码)
注意
计算的时候 (n-1)*(n-2)可能会超 int 范围, 所以要用 long long
参考代码 - 有疑问的地方在下方留言 看到会尽快回复的
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>

using namespace std;

typedef long long LL;

const int MAXN = 1e2 + 10;
const LL INF = 1LL<<62;

int main() {
  LL n, m, v;
  while(cin>>n>>m>>v) {
    LL tmp = (n-1)*(n-2)/2 + 1;
    if(m >= (n-1) && m <= tmp) {
      int tk = 1, mark = (v == n ? n-1:n);
      cout<<v<<" "<<mark<<endl;
      for( int i=1; i<n && tk != m; i++ ) {
        for( int j=i+1; j<=n; j++ ) {
          if(j == mark) continue;
          cout<<i<<" "<<j<<endl;
          tk++;
          if(tk == m) break;
        }
      }
    }
    else printf("-1\n");
  }
  return 0;
}

抱歉!评论已关闭.