uva 10160 Servicing stations


参考uva 10160 Servicing Stations(DFS+剪枝)


#include "stdio.h"
#include "string.h"
#include "algorithm"
using namespace std;
//map保存联通关系,vis保存是否有服务,son记录每个点与他联通点的个数
int map[40][40],vis[40],son[40],n,m,ans;

bool cmp(int x,int y)
{
	return  x>y;
}

//cur当前搜索的位置,cnt当前联通点的数量,sum服务站的数量
void dfs(int cur ,int cnt ,int sum)
{
	int i,k;
	if(sum>=ans) return;//某条路未搜索完,服务站数量就大于之前最小的答案
	if(cnt==n) ans=sum;

	for(i=1;i<cur;i++)//某点未联通服务,且与之相关的点都已经搜索过
		if(!vis[i]&&map[i][0]<cur) return;

	dfs(cur+1,cnt,sum);

	k=0;//记录某点成为服务站后新增加的有服务点的个数
	int li[40];//记录有新增加有服务点的标号
	for(i=0;i<son[cur];i++)
	{
		if(vis[map[cur][i]]==0)
		{
			vis[map[cur][i]]=1;
			li[k++]=map[cur][i];

		}
	}
	if(!k) return;//新增加有服务点的数目为零
	dfs(cur+1,cnt+k,sum+1);//搜索下一个
	for(i=0;i<k;i++)//回溯,将所有上面新增点恢复未服务状态
	vis[li[i]]=0;

}

int main()
{
	int i,j,a,b;
	while(~scanf("%d%d",&n,&m)&&n&&m)
	{
		memset(vis,0,sizeof(vis));
		memset(map,0,sizeof(map));
		memset(son,0,sizeof(son));
		ans=n+1;
		for(i=0;i<m;i++)
		{
			scanf("%d%d",&a,&b);
			map[a][son[a]++]=b;
			map[b][son[b]++]=a;
		}
		for(i=1;i<=n;i++)
        {
            map[i][son[i]++]=i;//将其中一点与自己相同,防止最后一点为服务站时出错
            sort(map[i],map[i]+son[i],cmp);
        }
		dfs(1,0,0);
		printf("%d\n",ans );

	}
	return 0;
}


你可能感兴趣的:(uva 10160 Servicing stations)