HDU 6150 Vertex Cover【构造二分图】

来源:互联网 发布:楼月软件注册码 编辑:程序博客网 时间:2024/06/06 19:28

source:

2017中国大学生程序设计竞赛 - 网络选拔赛


题意:这是2017中国大学生程序设计竞赛网络选拔赛的题1。首先题目给你一个求最小顶点覆盖的近似算法:每次取度数最大的点删去它和其关联的所有边,继续该过程直到完成覆盖。现要求构造一个图来“卡”这个算法,就是说要构造一个足够“坏”的图,使得按照题目该出的近似算法求出的顶点覆盖集的规模>=你能给出的顶点覆盖规模。输出构造的图和给出你的顶点覆盖。

思路:

    看到此题时以为只用在演算纸上画出符合条件的图,然后程序直接输出,而事实证明并没这么简单,还是需要运用步骤性的算法解决。其实首先可以这样思考,假如我的顶点覆盖方案有n个点,那么要让近似算法选3*n个点,不妨直接构造成二分图,左边n个点,右边3n个点,现在目的便是连边使得近似算法取右边作为顶点覆盖即可。

    连边的话倒着来想即可,右边取到最后只剩一个点(不妨设为n+1号点)时,要保证取n+1号点,那么该点至少连一条边到左边点集即可,这里要注意一点:留意近似算法是度数相同时取编号大的,所以预留的1~n号为自个儿方案的点就是这个目的。好继续倒推,对于n+2号点也只需连一条边到左边点集,不与刚刚n+1号点连的相同即可,依次类推一直到2n号点都只需连一条线,而对于2n+1号点,由于左边点集现在都已经度数为1了,所以2n+1号点至少要连两条边,这样这三个点都是度数为2,优先取2n+1满足条件,如此思路倒推回去....右边点集可以构造出来的点数:度数为1的有n个点,度数为2点的n/2,n/3,n/4.... n/k   求和只要大于3n即可

    我取n=50大概算了一下,k=12即可。

代码如下:

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int main(){    int n=50; //n为二分图左边的点数+3n为二分图右边点数    int tot=0,m=0,weight=1;    for(int i=n+1;i<=4*n;i++)    {        m+=weight;        tot+=weight;        if(tot+weight>n)        {            weight++;            tot=0;        }    }//以上统计边数m    printf("%d %d\n",4*n,m);    weight=1;    tot=0;    for(int i=n+1;i<=4*n;i++)    {        for(int j=tot+1;j<=tot+weight;j++)        {            printf("%d %d\n",j,i);            m++;        }        tot+=weight;        if(tot+weight>n)        {            weight++;            tot=0;        }    }    printf("%d\n",n);    for(int i=1;i<=n;i++) printf("%d\n",i);    return 0;}