其他分享
首页 > 其他分享> > 洛谷 P6822 - [PA2012]Tax(点转边+最短路)

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

作者:互联网

洛谷题面传送门

套路题一道。

首先直接抛出建图方式:

然后跑 \(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