求一般圖的最小頂點覆蓋集問題的混合貪婪算法(近似算法)
阿新 • • 發佈:2017-10-07
混合 論文 之前 blog tor col mes 偏差 cnblogs
之前準備做hiho一下的時候,網上查關於無向圖的最大獨立集;
看到了一篇論文,說是能“求一般圖的最小頂點覆蓋集問題”的混合貪婪算法;
我一看覺得挺牛逼的啊,跑去研究了大半天的這篇論文,發現實際還是一個很一般的近似算法,在特殊情況下偏差極大;
實現完之後實際去做題,發現連樣例都過不了,我還以為程哪裏寫挫了,
仔細一看,樣例產生的無向圖就是一個對本算法十分不友好的情況,
看來想在搞算法題的時候用是不大現實了,不過好歹算是研究了一篇論文,還手動實現了一遍;
當然,這個算法在圖的規模較大的情況下,應該擁有較好的近似比,可以考慮在某些特定場景下使用;
論文連接clickhere;
具體實現:
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 */
求一般圖的最小頂點覆蓋集問題的混合貪婪算法(近似算法)