C. 连锁商店 (暴力优化)

本文介绍了一个关于旅游胜地比特山的问题,涉及到景点间的缆车路线和商店红包。每个景点的商店属于不同的公司,每个公司提供新客优惠红包。通过Floyd算法优化路线,找到从1号景点出发到达各景点的最优路径,以获得最大红包总额。程序采用深度优先搜索策略,结合Floyd算法避免重复路线,并输出每个目的地的最大红包金额。
摘要由CSDN通过智能技术生成

比特山是一个旅游胜地,它一共有 nn 个景点,按照海拔高度从低到高依次编号为 11 到 nn。为了更好地帮助游客们欣赏这里的风景,人们在上面搭建了 mm 条缆车路线。每条缆车路线只可能把游客们从某个海拔较低的景点运送到另一个海拔较高的景点。

在每个景点都有一家纪念品连锁商店,其中第 ii 个景点的商店隶属第 cici 号公司,两家连锁店 (i,j)(i,j) 隶属同一公司当且仅当 ci=cjci=cj。每家公司都有新客优惠活动,其中第ii家公司对于新客的优惠红包为 wiwi 元,一旦领取了隶属该公司的某家连锁店的一份红包,就不能再领取该公司所有分店的红包。

你正在 11 号景点,你将会搭乘缆车去往各个景点,每到一个景点,你都可以领取该景点的连锁商店的新客优惠红包(包括 11 号景点)。当然,同一家公司的红包最多只能领一次。请写一个程序,对于每个可能的终点 kk,找到一条从 11 号景点出发到达 kk 号景点的游览路线,使得可以领取到总金额最多的优惠红包。

Input

第一行包含两个正整数 n,mn,m (2≤n≤362≤n≤36, 1≤m≤n(n−1)21≤m≤n(n−1)2),分别表示景点的数量以及缆车路线的数量。

第二行包含 nn 个正整数 c1,c2,…,cnc1,c2,…,cn (1≤ci≤n1≤ci≤n),依次表示每个景点的商店所隶属的公司。

第三行包含 nn 个正整数 w1,w2,…,wnw1,w2,…,wn (1≤wi≤1061≤wi≤106),依次表示每家公司的新客优惠红包的金额。

接下来 mm 行,每行两个正整数 ui,viui,vi (1≤ui<vi≤n1≤ui<vi≤n),表示一条缆车路线,起点是景点 uiui,终点是景点 vivi。输入数据保证任意两个景点之间最多只有一条缆车路线,且从 11 号景点出发可以到达任意一个景点。

Output

输出 nn 行,第 ii 行输出一个整数,即从 11 号景点出发到达 ii 号景点时,领取的优惠红包的总金额的最大值。

Example

input

Copy

5 5
1 2 2 3 4
1 4 5 9 3
1 2
2 3
3 5
1 4
4 5

output

Copy

1
5
5
6
15

思路:点很少但是会有一个点连很多个点的情况

那么我们就考虑,比如说1-6是一条路,1-2-6也是一条路

那么显然1-2-6走的点更多,能收到更多红包

那么我们就用Floyd优化一下,如果i j之间有一条路,i k,k j之间也有路,那么把i j之间的路给删掉

然后正常深搜就行

#include<bits/stdc++.h>
using namespace std;
int n,m;
int c[40];
int w[40];
vector<int> v[100];
int g[40][40];
int ans[40];
map<int,int> mp;
void dfs(int u,int con){//走到第u个点的时候,当前得到红包的值
	ans[u]=max(ans[u],con);//更新
	for(auto i:v[u]){//遍历与u相连的点
	//	cout<<"u=="<<u<<" i=="<<i<<endl;
		if(mp[c[i]]==0){//如果没被收过
			mp[c[i]]=1;
			dfs(i,con+w[c[i]]);
			mp[c[i]]=0;//回溯
		}else dfs(i,con);
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>c[i];
	for(int i=1;i<=n;i++)cin>>w[i];
	while(m--){
		int a,b;
		cin>>a>>b;
		g[a][b]=1;
	}
	//Floyd优化图
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			for(int k=j+1;k<=n;k++){
				if(g[i][k]&&g[i][j]&&g[j][k]){
					g[i][k]=0;
				}
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			if(g[i][j]){
				v[i].push_back(j);
			}
		}
	}
	ans[1]=w[c[1]];
	mp[c[1]]=1;
	dfs(1,w[c[1]]);
	for(int i=1;i<=n;i++)cout<<ans[i]<<endl;
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值