CF1725M Moving Both Hands 绿 题解

Part0:前言

奆佬们怎么都说这题是两只手,我英文还是太菜了,就按红蓝两球来讲吧。


Part1:思路

显然,对于每局游戏,可将蓝球移动化为红球在反图上移动,需经过的边不变。于是我们就可以自然地想到使用分层图。

不同边的含义如下:

  • 对于边 \((u,v,w)\),表示正图的边。

  • 对于边 \((v+n,u+n,w)\),表示反图的边。

  • 对于边 \((i,i+n,0)\),表示从 \(i\) 开始走反图。

最终的输出即为 \(1 \to i+n\) 的最短路程。


Part2:代码

#include <bits/stdc++.h>
using namespace std;
#define int long long

int n,m,k,tot,hd[2000010],nx[2000010],to[2000010],vl[2000010],dis[2000010];
bool vis[2000010];

void add (int u,int v,int w) {
	nx[++tot]=hd[u];
	to[tot]=v;
	vl[tot]=w;
	hd[u]=tot;
}

signed main () {
	cin>> n>> m;
	for (int i=1,u,v,w;i<=m;i++) {
		cin>> u>> v>> w;
		add (u,v,w);
		add (v+n,u+n,w);
	}
	for (int i=1;i<=n;i++)
		add (i,i+n,0); 
	priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > heap;
	memset (dis,0x3f,sizeof dis);
	heap.push ({0,1});
	dis[1]=0;
	while (heap.size ()) {
		int u=heap.top ().second;
		heap.pop ();
		if (vis[u]) continue;
		vis[u]=1;
		for (int i=hd[u];i;i=nx[i]) {
			int v=to[i],w=vl[i];
			if (dis[v]>dis[u]+w) {
				dis[v]=dis[u]+w;
				heap.push ({dis[v],v});
			}
		}
	}
	for (int i=n+2;i<=n*2;i++)
		cout<< (dis[i]==0x3f3f3f3f3f3f3f3f? -1: dis[i])<< " ";
	return 0;
}
#include <bits/stdc++.h>
using namespace std;
#define int long long

int n,m,k,tot,hd[2000010],nx[2000010],to[2000010],vl[2000010],dis[2000010];
bool vis[2000010];

void add (int u,int v,int w) {
	nx[++tot]=hd[u];
	to[tot]=v;
	vl[tot]=w;
	hd[u]=tot;
}

signed main () {
	cin>> n>> m;
	for (int i=1,u,v,w;i<=m;i++) {
		cin>> u>> v>> w;
		add (u,v,w);
		add (v+n,u+n,w);
	}
	for (int i=1;i<=n;i++)
		add (i,i+n,0); 
	priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > heap;
	memset (dis,0x3f,sizeof dis);
	heap.push ({0,1});
	dis[1]=0;
	while (heap.size ()) {
		int u=heap.top ().second;
		heap.pop ();
		if (vis[u]) continue;
		vis[u]=1;
		for (int i=hd[u];i;i=nx[i]) {
			int v=to[i],w=vl[i];
			if (dis[v]>dis[u]+w) {
				dis[v]=dis[u]+w;
				heap.push ({dis[v],v});
			}
		}
	}
	for (int i=n+2;i<=n*2;i++)
		cout<< (dis[i]==0x3f3f3f3f3f3f3f3f? -1: dis[i])<< " ";
	return 0;
}

Part3:后记

分层图板题,如果想要练手的话,还可以做一做 P4568P4822 等题。

posted @ 2025-03-04 20:52  M_CI  阅读(13)  评论(0)    收藏  举报