ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

洛谷 P6822 - [PA2012]Tax(点转边+最短路)

2022-05-06 11:04:59  阅读:194  来源: 互联网

标签:洛谷 int PA2012 MAXM Tax ec 权值 const dis


洛谷题面传送门

套路题一道。

首先直接抛出建图方式:

  • 边化点,点转边。将每一条无向边 \(e=(u,v,w)\) 拆成一正一反两条有向边 \(e_1,e_2\),然后在 \(e_1,e_2\) 之间连权值为 \(w\) 的边。

  • 对于每个点,将所有与其相连的边按权值从小到大排序,然后对于权值相邻的两条边 \((e_1,w_1),(e_2,w_2)(w_1<w_2)\),连边 \(e_1\to e_2\),权值 \(w_2-w_1\),以及 \(e_2\to e_1\),权值 \(0\)。

  • 新建起点 \(S\) 和终点 \(T\),对于一条边,如果起点为 \(1\) 则从 \(S\) 向这条边连权值为这条边权值的边;如果终点为 \(n\) 则从这条边向 \(T\) 连权值为这条边权值的边。

然后跑 \(S\) 到 \(T\) 的最短路即可。

为什么?考虑将原图中一条路径对应到我们建出来的图中,假设这条路径为 \(1=p_1\to p_2\to p_3\to\cdots\to p_k=n\),经过的边分别为 \(e_1,e_2,\cdots,e_{k-1}\),那么对应到我们建出来的这张图中,这条路径映射到的路径就是 \(S\to e_1\to e_1\text{的反向边}\to e_2\to e_2\text{的反向边}\to\cdots\to e_{k-1}\to T\)。\(1,n\) 的贡献分别在 \(S\to e_1,e_{k-1}\to T\) 这两条边中体现,而对于一个非起点也非终点的 \(p_i\),如果前一条边 \(e_i\) 的权值 \(>e_{i+1}\) 的权值,那么在经过 \(e_i\to e_i\text{的反向边}\) 这条边后,必然会沿着 \(0\) 权边走到 \(e_{i+1}\),此时这个点的贡献就是 \(e_i\) 的权值,反之在经过 \(e_i\to e_i\text{的反向边}\) 这条边后,必然会沿着总权值为 \(e_{i+1}-e_i\) 的边走到 \(e_{i+1}\),此时这个点的贡献就是 \(e_{i+1}\) 的权值,因此在新图中我们映射到的路径的权值就是原图中这条路径的答案。

时间复杂度 \(m\log m\)。

const int MAXN = 1e5;
const int MAXM = 2e5;
int n, m;
int hd[MAXM * 2 + 5], nxt[MAXM * 10 + 5], val[MAXM * 10 + 5], to[MAXM * 10 + 5], ec = 0;
void adde(int u, int v, int w) {
//	printf("adde %d %d %d\n", u, v, w);
	to[++ec] = v; val[ec] = w;nxt[ec] = hd[u]; hd[u] = ec;
}
struct edge {
	int u, v, w, id;
	friend bool operator < (const edge &X, const edge &Y) {
		return X.w < Y.w;
	}
};
vector<edge> g[MAXN + 5];
ll dis[MAXM * 2 + 5];
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1, u, v, w; i <= m; i++) {
		scanf("%d%d%d", &u, &v, &w);
		g[u].pb({u, v, w, i << 1});
		g[v].pb({v, u, w, i << 1 | 1});
		adde(i << 1, i << 1 | 1, w);
		adde(i << 1 | 1, i << 1, w);
	}
	for (int i = 1; i <= n; i++) {
		sort(g[i].begin(), g[i].end());
		for (int j = 1; j < g[i].size(); j++) {
			adde(g[i][j].id, g[i][j - 1].id, 0);
			adde(g[i][j - 1].id, g[i][j].id, g[i][j].w - g[i][j - 1].w);
		}
		if (i == 1) for (int j = 0; j < g[i].size(); j++) adde(0, g[i][j].id, g[i][j].w);
		if (i == n) for (int j = 0; j < g[i].size(); j++) adde(g[i][j].id ^ 1, 1, g[i][j].w);
	}
	memset(dis, 63, sizeof(dis)); dis[0] = 0;
	priority_queue<pair<ll, int>, vector<pair<ll, int> >, greater<pair<ll, int> > > q;
	q.push(mp(0, 0));
	while (!q.empty()) {
		auto p = q.top(); q.pop(); int x = p.se;
		for (int e = hd[x]; e; e = nxt[e]) {
			int y = to[e], z = val[e];
			if (dis[y] > dis[x] + z) {
				dis[y] = dis[x] + z;
				q.push(mp(dis[y], y));
			}
		}
	}
	printf("%lld\n", dis[1]);
	return 0;
}

标签:洛谷,int,PA2012,MAXM,Tax,ec,权值,const,dis
来源: https://www.cnblogs.com/ET2006/p/luogu-P6822.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有