hdu 6150

来源:互联网 发布:淘宝客单页网站源码 编辑:程序博客网 时间:2024/06/04 18:29

Vertex Cover

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others)
Total Submission(s): 448    Accepted Submission(s): 173
Special Judge


Problem Description
As we know, minimumvertexcover is a classical NP-complete problem. There will not be polynomial time algorithm for it unless P=NP.

You can see the definition of vertex cover in https://en.wikipedia.org/wiki/Vertex_cover.

Today, little M designs an "approximate" algorithm for vertex cover. It is a greedy algorithm. The main idea of her algorithm is that always choosing the maximum degree vertex into the solution set. The pseudo code of her algorithm is as follows:

We assume that the labels of the vertices are from 1 to n.

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;


As a theory computer scientist, you immediately find that it is a bad algorithm. To show her that this algorithm dose not have a constant approximate factor, you need to construct an instance of vertex cover such that the solution get by this algorithm is much worse than the optimal solution.

Formally, your program need to output a simple undirected graph of at most 500 vertices. Moreover, you need to output a vertex cover solution of your graph. Your program will get Accept if and only if the solution size get by the above algorithm is at least three times as much as yours.
 

Input
There is no input.
 

Output
First, output two integer n and m in a line, separated by a space, means the number of the vertices and the number of the edges in your graph.
In the next m lines, you should output two integers u and v for each line, separated by a space, which denotes an edge of your graph. It must be satisfied that 1u,vn and your graph is a simple undirected graph.
In the next line, output an integer k(1kn), means the size of your vertex cover solution.
Then output k lines, each line contains an integer u(1un) which denotes the label of a vertex in your solution. It must be satisfied that your solution is a vertex cover of your graph.
 

Sample Output
4 4
1 2
2 3
3 4
4 1
2
1
3

Hint

The sample output is just to exemplify the output format.

 

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

Recommend
liuyiding  &nbsp|  &nbspWe have carefully selected several similar problems for you:  6160 6159 6158 6157 6156 
 

Statistic | Submit | Discuss | Note

题目给了个求无向图最小点覆盖的方法,直接贪心的每次都选出一个度最大的点,然后覆盖掉这个点周围的边。要输出一个图,贪心算法选的点要比正解多了三倍。这明显是一个错误的方法。因为这种贪心解决不了当有两个度数一样的点,先选哪个好的问题。然后比赛的时候只是一直想着构造多几个度数相同的点让他选错,没弄出其中的奇妙啊。
这里写图片描述
博客地址

这种想法是分成左右两组,左边的点是正解,右边的点那个贪心算法会选错的。
方法
如图,绿色的点是左边的点,黑色的点是右边的点,线段表示黑色的点跟谁连绿色的点连结上了。按照这种方法来连,那么黑色17是度最大的,会被先选上,然后绿色1~10都会度减一,此时16又变成最大了的,这样重复下去,终究是右边的全都被选上了啊。点数多一些的话,右边的点就会是左边的三倍。

#include<bits/stdc++.h>using namespace std;vector<pair<int,int>> e;int main(){    if (fopen("in.txt", "r") != NULL)    {        freopen("in.txt", "r", stdin);        freopen("out.txt", "w", stdout);    }    int l=100,r=100;    for(int i=2;i<=l;i++)    {        for(int j=1;j*i<=l;j++)        {            r++;            for(int k=i*(j-1)+1;k<=i*j;k++)                e.push_back({r,k});        }    }    cout<<r<<" "<<e.size()<<endl;    for(auto ei : e)        cout<<ei.first<<" "<<ei.second<<endl;    cout<<l<<endl;    for(int i=1;i<=l;i++)        cout<<i<<endl;    return 0;}