poj 1935(搜索+回溯)



解题思路: 先我们考虑从源点出发到所有自己想要经过的点然后在回到源点sum,显然每条边都必须经过源点(这个我们可以一次dfs求出),但题目的意思是可以不用回到源点,那么我们可以再求源点到所有要经过的点的最远距离ans,于是答案便是sum-ans.

这道题的思路确实是很巧妙,一开始我还是在想如何表示从某一点回来的状态,数据太大用状态压缩肯定不行,结果就没思路了,看了别人的思路确实是抓住了这道题的精髓。。。


#include
#include
#include
using namespace std;

const int maxn = 50005;
struct Edge
{
	int w,v,next;
}edge[maxn<<1];
int n,m,k,pre[maxn],dis[maxn],cnt,sum;
bool vis[maxn];

void addedge(int u,int v,int w)
{
	edge[cnt].v = v;
	edge[cnt].w = w;
	edge[cnt].next = pre[u];
	pre[u] = cnt++;
}

void dfs(int u,int f)
{
	for(int i = pre[u]; i != -1; i = edge[i].next){
		int v = edge[i].v, w = edge[i].w;
		if(v == f) continue;
		dis[v] = dis[u] + w;
		dfs(v,u);
		if(vis[v]){
			sum += 2*w;
			vis[u] = true;
		}
	}
}

int main()
{
	while(scanf("%d%d",&n,&k)!=EOF){
		cnt = 0;
		memset(pre,-1,sizeof(pre));
		memset(vis,false,sizeof(vis));
		for(int i = 1; i < n; i++){
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			addedge(u,v,w);
			addedge(v,u,w);
		}
		scanf("%d",&m);
		while(m--){
			int u;
			scanf("%d",&u);
			vis[u] = true;
		}
		sum = 0; dis[k] = 0; m = 0;
		dfs(k,-1);
		for(int i = 1; i <= n; i++){
			if(vis[i] == false) continue;
			m = max(m,dis[i]);
		}
		printf("%d\n",sum - m);
	}
	return 0;
}

你可能感兴趣的:(搜索)