UVA - 10160 Servicing Stations(回溯+剪枝)

Problem D: Servicing stations


A company offers personal computers for sale in N towns (3 <= N <= 35). The towns are denoted by 1, 2, ..., N. There are direct routes connecting M pairs from among these towns. The company decides to build servicing stations in several towns, so that for any town X, there would be a station located either in X or in some immediately neighbouring town of X.

Write a program for finding out the minumum number of stations, which the company has to build, so that the above condition holds.

Input 
The input consists of more than one description of town (but totally, less than ten descriptions). Every description starts with number N of towns and number M of pairs of towns directly connected each other. The integers N and M are separated by a space. Every one of the next M rows contains a pair of connected towns, one pair per row. The pair consists of two integers for town's numbers, separated by a space. The input ends with N = 0 and M = 0.

Output
For every town in the input write a line containing the obtained minimum.

An example:

Input:

8 12
1 2
1 6
1 8
2 3
2 6
3 4
3 5
4 5
4 7
5 6
6 7
6 8
0 0

Output:

2


题目大意:一个公司销售个人电脑,在n个城镇建立服务站,n个城镇有m条道路,每个服务可以服务但前的城镇,和当前城镇相连接的城镇,问最少要建立多少个服务站?

解析:本题采用回溯法,但是单纯的只回溯不剪枝会超时,因为最多有35个城镇,即要枚举2^35中情况,可想而知会超时。
所以这题的做法是建立临接表来保存两节点连接
有4个剪枝:
1、当前的服务站个数大于原先的答案,显然后面只会变大,返回。
2、当前已经覆盖的结点等于n即全部覆盖了,那么返回答案,出口。
3、如果当前枚举的点编号大于n返回。
4、最重要,最难想到的一个剪枝,当出现前面有的已经无法被覆盖,那么后面不可能再覆盖这个点,返回。


#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 36;
int n,m;
int edge[N][N];
int vis[N];
int s[N];
int ans;

void dfs(int u,int sum,int cur) {
	if(cur == n && sum < ans) {
		ans = sum;
		return;
	}
	if(u > n || sum >= ans) {
		return;
	}
	for(int i = 1; i < u; i++) {
		if( !vis[i] && edge[i][s[i]-1] < u) {
			return ;
		}
	}
	int cnt = 0;
	for(int i = 0; i < s[u]; i++) {
		if( !vis[edge[u][i]] ) {
			cnt++;
		}
		vis[edge[u][i]]++;
	}
	if(cnt) {
		dfs(u+1,sum+1,cur+cnt);
	}
	for(int i = 0; i < s[u]; i++) {
		vis[edge[u][i]]--;
	}
	dfs(u+1,sum,cur);
}
int main() {
	int u,v;
	while(scanf("%d%d",&n,&m) != EOF && (n || m)) {
		memset(edge,0,sizeof(edge));
		memset(s,0,sizeof(s));
		memset(vis,0,sizeof(vis));

		for(int i = 0; i < m; i++) {
			scanf("%d%d",&u,&v);
			edge[u][s[u]++] = v;
			edge[v][s[v]++] = u;
		}
		for(int i = 1; i <= n; i++) {
			edge[i][s[i]++] = i;
			sort(edge[i],edge[i]+s[i]);
		}
		ans = n;
		dfs(1,0,0);
		printf("%d\n",ans);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dism(Deployment Image Servicing and Management)是Windows操作系统中的一个命令行工具,主要用于管理和维护系统映像(如Windows安装映像文件或预安装环境映像文件)和组件存储库。 Dism命令中的恢复功能-修复受损提供了一种修复系统映像或组件存储库中受损组件的方法。当系统中的某个组件或功能无法正常运行或受到破坏时,可以使用Dism命令来修复。 使用Dism命令修复受损的组件可以解决许多常见的系统问题,如应用程序无法打开、系统错误提示、文件损坏等。修复受损的组件可以使系统恢复正常运行,避免重新安装整个操作系统或进行其他复杂的修复过程。 具体操作步骤如下: 1. 打开命令提示符或Windows PowerShell以管理员身份运行。 2. 输入以下命令:dism /online /cleanup-image /restorehealth 这将启动修复过程并自动下载和替换受损文件。 3. 等待修复过程完成。根据系统的情况和网络速度,可能需要几分钟或更长的时间。 请注意,只有在以管理员身份运行的命令提示符或Windows PowerShell中才能使用Dism命令进行修复。修复过程可能需要联网下载修复文件,并且可能需要重新启动系统才能使修复生效。 总结而言,Dism恢复功能-修复受损提供了一种方便快捷地修复Windows系统中受损组件的方法,可以帮助解决系统出现的一些常见问题。在使用Dism命令进行修复时,请确保按照正确的步骤操作,并理解修复过程可能需要一定时间和网络资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值