求一般图的最小顶点覆盖集问题的混合贪婪算法(近似算法)
Posted tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求一般图的最小顶点覆盖集问题的混合贪婪算法(近似算法)相关的知识,希望对你有一定的参考价值。
之前准备做hiho一下的时候,网上查关于无向图的最大独立集;
看到了一篇论文,说是能“求一般图的最小顶点覆盖集问题”的混合贪婪算法;
我一看觉得挺牛逼的啊,跑去研究了大半天的这篇论文,发现实际是求近似解的,在特殊情况下偏差极大;
实现完之后拿去做题,发现连样例都过不了,差点还以为程序哪里写挫了,
仔细一看,正好样例产生的无向图就是一个对本算法十分不友好的情况,
看来想在搞算法题的时候用是不大现实了,不过好歹算是研究了一篇论文,还手动实现了一遍;
当然,这个算法在图的规模较大的情况下,应该拥有较好的近似比,可以考虑在某些特定场景下使用;
具体实现:
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<queue> 5 #include<algorithm> 6 #define MAX 20 7 using namespace std; 8 int n,m; 9 struct Edge{ 10 int u,v; 11 }; 12 struct Point{ 13 int id; 14 int degree,adj_degree; 15 }point[MAX]; 16 vector<Edge> E; 17 vector<int> G[MAX]; 18 int degree[MAX],adj_degree[MAX];//每个点的度数和邻接度数 19 bool del[MAX],vis[MAX]; 20 int V_cnt,Vv_cnt,E_cnt; 21 void init_edge() 22 { 23 E.clear(); 24 for(int i=1;i<=n;i++) G[i].clear(); 25 } 26 void add_edge(int u,int v) 27 { 28 E.push_back((Edge){u,v}); 29 E.push_back((Edge){v,u}); 30 int _size=E.size(); 31 G[u].push_back(_size-2); 32 G[v].push_back(_size-1); 33 } 34 bool cmp(Point a,Point b){return a.adj_degree>b.adj_degree;} 35 int pretreat() 36 { 37 for(int i=1;i<=n;i++) 38 { 39 point[i].degree=0; 40 if(del[i]) continue; 41 for(int j=0,_size=G[i].size();j<_size;j++) 42 { 43 Edge& e=E[G[i][j]]; 44 if(!del[e.v]) point[i].degree++; 45 } 46 if(point[i].degree==0) del[i]=1; 47 } 48 for(int i=1;i<=n;i++) 49 { 50 if(del[i]) 51 { 52 point[i].adj_degree=0; 53 continue; 54 } 55 point[i].adj_degree=point[i].degree; 56 for(int j=0,_size=G[i].size();j<_size;j++) point[i].adj_degree+=point[E[G[i][j]].v].degree; 57 printf("adj_degree[%d] = %d\\n",i,point[i].adj_degree); 58 } 59 sort(point+1,point+n+1,cmp); 60 } 61 void MinVC_MGA(bool ans[]) 62 { 63 memset(del,0,sizeof(del)); 64 for(int i=1;i<=n;i++) point[i].id=i; 65 E_cnt=0; 66 while( E_cnt < m ) 67 { 68 memset(vis,0,sizeof(vis)); 69 pretreat(); 70 V_cnt=0; 71 Vv_cnt=0; 72 for(int i=1;i<=n;i++) if(!del[i]) Vv_cnt++; 73 for(int i=1;i<=n;i++) 74 { 75 printf("del[%d]=%d vis[%d]\\n",point[i].id,del[point[i].id],point[i].id,vis[point[i].id]); 76 if(del[point[i].id]) continue; 77 if(vis[point[i].id]) continue; 78 printf("now ans add: %d\\n",point[i].id); 79 ans[point[i].id]=1;//加入到最小顶点覆盖集中 80 del[point[i].id]=1, Vv_cnt--; 81 for(int j=0,_size=G[point[i].id].size();j<_size;j++) 82 { 83 Edge& e=E[G[point[i].id][j]]; 84 if(del[e.v]) continue; 85 E_cnt++; 86 if(!vis[e.v]) 87 { 88 vis[e.v]=1; 89 V_cnt++; 90 } 91 } 92 if(V_cnt>=Vv_cnt) break; 93 } 94 } 95 } 96 97 int main() 98 { 99 while(scanf("%d %d\\n",&n,&m)!=EOF) 100 { 101 init_edge(); 102 for(int i=1,u,v;i<=m;i++) 103 { 104 scanf("%d%d",&u,&v); 105 add_edge(u,v); 106 } 107 bool ans[n+5]; 108 memset(ans,0,sizeof(ans)); 109 MinVC_MGA(ans); 110 for(int i=1;i<=n;i++) printf("%d:%s\\n",i,ans[i]?"YES":"NO"); 111 } 112 } 113 /* 114 13 17 115 1 10 116 1 2 117 1 7 118 10 11 119 7 11 120 7 3 121 7 8 122 11 8 123 3 4 124 4 9 125 8 9 126 8 12 127 9 12 128 5 9 129 12 13 130 5 6 131 6 13 132 */
以上是关于求一般图的最小顶点覆盖集问题的混合贪婪算法(近似算法)的主要内容,如果未能解决你的问题,请参考以下文章