uva10160Servicing Stations

来源:互联网 发布:java视频点播系统源码 编辑:程序博客网 时间:2024/06/06 18:36

这道题我各种坑,各种条件写错。。。总之自己心态没有调整好,总想着尽快A题,不向往把原理弄懂。。。必须改变自己


题意就是给你一个图,对这个图上的节点染色,使得每个节点要么自己被染色,要么它的一个邻接节点被染色,求需要染色的最小节点数量。

直接brute force显然不行,需要进行剪枝:

1、度数为1的点,提前染色

2、按节点度数从大到小排序后再操作,这个利用了贪心法一般可以得到近似最优解的原理(不过实测不排序反而更快)

3、对于已经处理过的点,若点的颜色为0,且没有处理的点中没有于它邻接的点。这种情况直接return

4、若一个节点周围的点和它自己都已被染色,就直接跳过去到下一个点(这个看似可优化可不优化,实际上必不可少)



#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,m,all,small;char map[40][40],color[40];struct node{int index;int all;}nod[40];int cmp(node a,node b){return a.all > b.all;}void dfs(int index,int all){if(all>=small){return ;}int i,j,t=0;if(index==n+1){for(i=1;i<=n;i++)//少了这处{if(color[i]==0)break;}if(i==n+1){small=all;}return ;}char temp,tem[40];for(i=1;i<index;i++)//应该是小于index!! 脑残了。。。。{if(color[nod[i].index]==0){for(j=index;j<=n;j++){if(map[nod[i].index][nod[j].index]&&color[nod[j].index]!=2)//条件写错&&color[nod[j].index]!=2break;}if(j==n+1){return ;}}}for(i=index;i<=n;i++){if(map[nod[index].index][nod[i].index]&&color[nod[i].index]==0)//&&color[nod[i].index]==0条件错误break;}if(i==n+1&&color[nod[index].index]!=0)//这步优化很重要dfs(index+1,all);else{dfs(index+1,all);if(color[nod[index].index]!=2){temp=color[nod[index].index];color[nod[index].index]=2;for(i=1;i<=n;i++){if(map[nod[index].index][nod[i].index]&&color[nod[i].index]==0){color[nod[i].index]=1;tem[t++]=i;}}dfs(index+1,all+1);color[nod[index].index]=temp;for(i=0;i<t;i++)color[nod[tem[i]].index]=0;}}}int main(){int i,j,a,b,temp;while(scanf("%d %d",&n,&m)&&n+m){memset(map,0,1600);memset(color,0,40);all=0;small=40;for(i=0;i<m;i++){scanf("%d %d",&a,&b);map[a][b]=map[b][a]=1;}for(i=1;i<=n;i++){temp=0;for(j=1;j<=n;j++){if(map[i][j])temp++;}nod[i].index=i;nod[i].all=temp;}sort(nod+1,nod+n+1,cmp);for(i=n;nod[i].all==0&&i>=1;i--){color[nod[i].index]=2;all++;}if(all==n)small=n;elsedfs(1,all);printf("%d\n",small);}return 0;}


0 0