HDU 6150 Vertex Cover(构造)

256 篇文章 0 订阅

Description

给出一个求最小点覆盖的贪心算法,代码如下,要求构造一张顶点数不超过 500 的无向图使得该算法求出的点覆盖数是其最小点覆盖数的三倍以上,要求输出点数边数和每条边以及最小点覆盖集的点的编号

for (int i = 1; i <= n; ++i) {
  use[i] = false;
    deg[i] = degree of the vertex i;
}
int ans = 0;
while (true) {
  int mx = -1, u;
    for (int i = 1; i <= n; ++i) {
      if (use[i])
          continue;
        if (deg[i] >= mx) {
          mx = deg[i];
            u = i;
        }
    }
    if (mx <= 0)
      break;
    ++ans;
    use[u] = true;
    for (each vertex v adjacent to u)
      --deg[v];
}
return ans;

Input

无输入

Output

输出点数边数和每条边以及最小点覆盖集的点的编号

Sample Input

Sample Output

Solution

该算法即每次选出度数最大的点中编号最大的,直观想法是构造一个二分图,左边点有 n 个,右边点3n以上个,使得该算法选取的是右边的点,而真实最小点覆盖选左边的点即可,考虑对左边的点分块,第 i 次分块使得每块大小为i,然后对于每块都在右边新建一个节点与该块的每个节点连边,那么第一次就是新建 n 个节点与左边的点一一连,第二次就是新建n/2个节点,一个节点连向左边的两个节点,以此类推,右边的节点数即为 n+n/2+n/3+...+1nlogn ,取较大的 n 使得右边点数不小于3n是可以做到的,这样以来,左边点度数最大为 n 且只有第一个点度数是n,右边点度数有 n,n1,n2,... ,这样第一次会选取右边最后一个点,选取之后左边点最大度数为 n1 ,右边点最大度数也是 n1 ,仍然会选取右边的点,最后会选取所有右边的点作为一个点覆盖,而最小点覆盖取左边点即可,此构造满足要求

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=100001;
int main()
{
    int n=15,m=0;
    for(int i=1;i<=n;i++)m+=n/i*i;
    printf("%d %d\n",4*n,m);
    int res=n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n/i;j++)
            for(int k=1;k<=i;k++)
                printf("%d %d\n",(j-1)*i+k,res+j);
        res+=n/i;
    }
    printf("%d\n",n);
    for(int i=1;i<=n;i++)printf("%d\n",i);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值