HDU

最近的vj好垃圾,老崩,实名吐槽

HDU - 6150 

题意:给出一个错误的求最小点覆盖的函数,需要来构造一组样例,使得那个函数跑出来的答案是正解的3倍以上。

很巧妙的构造技巧,首先想法就是弄一个二分图,让正确答案是上面的n个点,我们需要构造的就是下面的点,这就不知道为什么要这样构造了。也就是分块的思想。

从1~n每次分n/i个块,每个块的大小为i,对于每个块下面就构造出一个点跟块里所有点相连。

这样下面的点就是n+n/2+n/3+n/4+...大约就是nlnn个点,那我们要求nlnn>=3n,n>=27就可以了。

正确性上面,下面的点的度数为,1个为n的,n/(n-1)个位n-1的...n个位1的,这样每次都是优先选下面的点。

 1 #include<cstdio>
 2 #include<vector>
 3 using namespace std;
 4 typedef pair<int,int> pii;
 5 vector<pii> vv;
 6 int main(){
 7     int u=30,v;
 8     for(int i=1;i<=30;i++){
 9         for(int j=0;j<30/i;j++){
10             u++;
11             for(int k=1;k<=i;k++){
12                 v=i*j+k;
13                 vv.push_back(pii(u,v));     
14             }
15         }
16     }
17     printf("%d %d
",u,(int)vv.size());
18     for(int i=0;i<vv.size();i++) printf("%d %d
",vv[i].first,vv[i].second);
19     printf("30
");
20     for(int i=1;i<=30;i++) printf("%d
",i);
21     return 0;
22 }
np
 1 #include<cstdio>
 2 #include<vector>
 3 using namespace std;
 4 const int N=10000;
 5 int vis[N],deg[N];
 6 vector<int> vv[N];
 7 int f(int n){
 8     int ans=0;
 9     while(true){
10         int mx=-1,u;
11         for(int i=1;i<=n;i++){
12             if(vis[i]) continue;
13             if(deg[i]>=mx){
14                 mx=deg[i];
15                 u=i;
16             }
17         }
18         if(mx<=0) break;
19         ans++;
20         vis[u]=1;
21         for(int i=0;i<(int)vv[u].size();i++) deg[vv[u][i]]--;
22     }
23     return ans;
24 }
25 int main(){
26     int n,m,u,v;
27     while(~scanf("%d%d",&n,&m)){
28         while(m--){
29             scanf("%d%d",&u,&v);
30             vv[u].push_back(v);
31             vv[v].push_back(u);
32             deg[u]++;
33             deg[v]++;   
34         }
35         //for(int i=1;i<=30;i++) printf("%d
",deg[i]);
36         printf("%d
",f(n));
37     }
38     return 0;
39 }
验证代码
原文地址:https://www.cnblogs.com/LMCC1108/p/11599332.html