abc188E- Peddler(DAG)

题目大意:

n个点,m条边
在n个点有一个物品买入和卖出的价值
m条边中保证x 问 对一个物品买卖一次的最大利润是多少

Solution 1:

因为边中保证了x mi[]定义为到达i点之前(不包括i点)的最小出买卖值
那么如果在i点进行交易的话,得到的利润为 val[i] - mi[i]
只需要枚举每个点 更新答案
然后用每个点的边集再更新一边 mi数组
复杂度O(N+M)

Solution 2:

如果题目的边中不保证x

对所有的点的买卖价值升序排列
选最便宜的点,然后进行bfs列举他能够到达的所有点
更新答案
ans = max(ans,val[u]-minn1)
然后选第二便宜的点
重复上述操作

走过的点可以不用再走
因为先选的minn1 所能够达到的点
如果minn2所能够到达的点中和minn1到达的点中有相同的点,那么一定是minn1更优
所以minn2的再次经过时可以忽略

Code1:

ll n,m,val[maxn];
vector<ll>e[maxn];
ll ans=-inf,mi[maxn];
int main() {
     
	n=read(),m=read();
	rep(i,1,n) val[i] = read(),mi[i] = inf;
	for(int i=1 ; i<=m ; i++) {
     
		int u,v;
		u=read(),v=read();
		e[u].push_back(v);
	}
	for(int i=1 ; i<=n ; i++) {
     
		ans = max(ans,val[i] - mi[i]);
		mi[i] = min(mi[i],val[i]);
		for(int j:e[i]) {
     
			mi[j]  = min(mi[j],mi[i]);
		}
	}
	out(ans);
	return 0;
}

Code2:

int n,m,ans=-inf,vis[maxn],val[maxn];
vector<int>e[maxn];
struct node {
     
	int num,id;
} a[maxn];
bool cmp(node x,node y) {
     
	return x.num<y.num;
}
void bfs(int st) {
     
	queue<int>q;
	q.push(a[st].id);
	while(q.size()) {
     
		int fr =q.front();
		q.pop();
		for(int v:e[fr]) {
     
			if(vis[v]) continue;
			vis[v]=1;
			ans = max(ans,val[v] - a[st].num);
			q.push(v);
		}
	}
}
int main() {
     
	n=read(),m=read();
	for(int i=1 ; i<=n ; i++) {
     
		a[i].id = i;
		val[i] = a[i].num = read();
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1 ; i<=m ; i++) {
     
		int u,v;
		u=read(),v=read();
		e[u].push_back(v);
	}
	for(int i=1 ; i<=n ; i++) {
     
		if(vis[i]) continue;
		bfs(i);
	}
	out(ans);
	return 0;
}

你可能感兴趣的:(训练,图论)