FZU 2169 shadow

FZU 2169 shadow


 思路:题目大意是求树上两点之间的路径,dfs和bfs均可

dfs:从王都一直深搜,如果搜到军队,则返回true,表明该dfs路径上的敌人均要消灭,最后输出ans,有一点要注意,用G++交会RE,C++交才AC,,
代码:
#pragma comment(linker,"/STACK:102400000:102400000")
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 100007
struct Edge{
	int v;
	int next;
	Edge(){}
	Edge(int a,int b):v(a),next(b){}
};
Edge edge[N*2];
int head[N],enemy[N];
bool vis[N];
int tot,ans; 
void init(){
	tot=0;
	memset(head,-1,sizeof(head));
	memset(vis,false,sizeof(vis));
}
void addEdge(int u,int v){
	edge[tot]=Edge(v,head[u]);
	head[u]=tot++;
}
bool dfs(int u,int pre){
	bool flag=vis[u];
	for(int i=head[u];i!=-1;i=edge[i].next){
		 int v=edge[i].v;
		 if(v==pre) continue;
		 flag=flag||vis[v];
		 flag=flag||dfs(v,u);
	}
	if(flag){
		ans+=enemy[u];
		enemy[u]=0;
	}
	return flag;
}
int main(){
	int n,k;
	while(scanf("%d%d",&n,&k)==2){
		init();
		for(int i=1;i<=n;++i){
			scanf("%d",&enemy[i]);
		}
		int tmp,u,v;
		for(int i=1;i<=k;++i){
			scanf("%d",&tmp);
			vis[tmp]=true;
		}
		for(int i=1;i<n;++i){
			scanf("%d%d",&u,&v);
			addEdge(u,v);
			addEdge(v,u);
		}
		ans=0; 
		dfs(1,-1);
		cout<<ans<<endl;
	}
	return 0;
}


bfs:以王都为根节点先进行一遍树的广搜,记录每个节点的前驱结点,用pre[i]存储,最后遍历军队的所在节点,一直找前驱结点,同时记录消灭敌人数,并用数组vis[i]标记该节点的敌人已被消灭,直到根节点王都
代码:
#pragma comment(linker,"/STACK:102400000:102400000")
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 100007
struct Edge{
	int v;
	int next;
	Edge(){}
	Edge(int a,int b):v(a),next(b){}
};
Edge edge[N*2];
int head[N],enemy[N],army[N],pre[N];
bool vis[N]; 
int tot,ans; 
void init(){
	tot=0;
	memset(head,-1,sizeof(head));
	memset(vis,false,sizeof(vis));
}
void addEdge(int u,int v){
	edge[tot]=Edge(v,head[u]);
	head[u]=tot++;
}
void bfs(int s){
	queue<int> q;
	pre[s]=s;
	q.push(s);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=head[u];i!=-1;i=edge[i].next){
			int v=edge[i].v;
			if(v==pre[u]) continue;
			pre[v]=u;
			q.push(v);
		}
	}
}
int main(){
	int n,k;
	while(scanf("%d%d",&n,&k)==2){
		init();
		for(int i=1;i<=n;++i){
			scanf("%d",&enemy[i]);
		}
		int u,v;
		for(int i=1;i<=k;++i){
			scanf("%d",&army[i]);
		}
		for(int i=1;i<n;++i){
			scanf("%d%d",&u,&v);
			addEdge(u,v);
			addEdge(v,u);
		}
		bfs(1);
		ans=0;
		for(int i=1;i<=k;++i){
			u=army[i];
			while(pre[u]!=u&&!vis[u]){
				ans+=enemy[u];
				vis[u]=true;
				enemy[u]=0;
				u=pre[u];
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值