求一般圖的最小頂點覆蓋集問題的混合貪婪算法(近似算法)


之前准備做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 */


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM