【Educational Codeforces Round 38 (Rated for Div. 2)】 Problem A-D 题解

23 篇文章 0 订阅
10 篇文章 0 订阅

【比赛链接】

           点击打开链接

【题解】

Problem A Word Correction【字符串】

不用多说了吧,字符串的基本操作


Problem B  Run for your prize【贪心】

我们可以将这个数轴一分为二,小于等于500000的由第一个人领,否则由第二个人领


Problem C Constructing tests【贪心】【数学】

首先我们发现 : N^2 - (N / M)^2 = x (N/M向下取整)

然后我们算出N的上下界,发现: sqrt(x+1)<=N<=sqrt(3/4*x)  (sqrt是开根号的意思)

所以我们可以枚举N,算出M


Problem D Buy a ticket【最短路】

首先想到可以跑N遍最短路

但是很显然,这样会超时,那么我们该如何优化呢?

我们不妨先建一个原点,将原点与每个城市连边,权值为在这个城市开演唱会的价格ai,然后再将城市与城市之间连边,

但是每条路径上的权值要乘2,因为是往返的费用

我们发现,只要对这个图跑一遍最短路,就得出了答案。

注意N最大10^5,SPFA不能过,要用dijkstra+堆优化

代码 : 

   

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MAXN = 2 * 1e5;

LL i,N,M;
LL dist[MAXN+10],a[MAXN+10],b[MAXN+10],c[MAXN+10],w[MAXN+10],vis[MAXN+10];
vector< pair<LL,LL> > E[MAXN+10];

template <typename T> inline void read(T &x) {
	LL f = 1; x = 0;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; }
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}

template <typename T> inline void write(T x) {
	if (x < 0) { putchar('-'); x = -x; }
	if (x > 9) write(x/10);
	putchar(x%10+'0');
}

template <typename T> inline void writeln(T x) {
	write(x);
	puts("");
}

inline void dijkstra(LL st) {
	LL i,x,to,cost;
	priority_queue< pair<LL,LL> > q;
	for (i = 1; i <= N; i++) dist[i] = LONG_LONG_MAX;
	q.push(make_pair(0,st));
	dist[st] = 0;
	memset(vis,0,sizeof(vis));
	while (!q.empty()) {
		x = q.top().second; q.pop();
		if (vis[x]) continue;
		vis[x] = 1; 
		for (i = 0; i < E[x].size(); i++) {
			to = E[x][i].first;
			cost = E[x][i].second;
			if (dist[x] + cost < dist[to]) {
				dist[to] = dist[x] + cost;
				q.push(make_pair(-dist[to],to));
			}
		}
	}	
}

int main() {
	
	read(N); read(M);
	for (i = 1; i <= M; i++) {
		read(a[i]); read(b[i]); read(w[i]);
		E[a[i]].push_back(make_pair(b[i],w[i]*2));
		E[b[i]].push_back(make_pair(a[i],w[i]*2));
	}
	for (i = 1; i <= N; i++) {
		read(c[i]);
		E[N+1].push_back(make_pair(i,c[i]));
	}
	dijkstra(N+1);
	for (i = 1; i <= N; i++) {
		if (i == 1) write(dist[i]);
		else { putchar(' '); write(dist[i]); }
	}
	puts("");
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值