ABC395E题解

大概评级:绿。

好简单的分层图啊!

只要做过分层图的题目,这道题就变得简单了,首先我先当大家都学会了迪杰斯特拉,那么我们只需要把迪杰斯特拉搬过来,然后你只需要再处理一个反向边建图,在迪杰斯特拉的结构体中加入一个 \(flag\) 变量,表示当前使用的是哪种图(正常图或者反向图),因为不断逆向边只会有两种图,然后我们把 \(d\) 数组和 \(vis\) 数组改成二维就行了,当然每次入队处理完后的最后要试一下逆向是否比当前存储的答案好。

代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int N = 2e5+5;
struct node
{
	int x;
	int w;
	int flag;
	bool operator<(const node&a)const
	{
		return w>a.w;
	}
};
vector<node>a[N];
vector<node>e[N];
priority_queue<node>q;
int d[N][2];
int vis[N][2];
signed main()
{
	int n,m,X;
	scanf("%lld %lld %lld",&n,&m,&X);
	for(int i = 1;i<=m;i++)
	{
		int x,y;
		scanf("%lld %lld",&x,&y);
		a[x].push_back({y,1});
		e[y].push_back({x,1});
	}
	memset(d,0x3f,sizeof(d));
	q.push({1,0,0});
	d[1][0] = 0;
	while(q.size())
	{
		int x = q.top().x;
		int flag = q.top().flag;
		int num = q.top().w;
		q.pop();
		if(vis[x][flag])
		{
			continue;
		}
		vis[x][flag] = 1;
		if(!flag)
		{
			for(int i = 0;i<a[x].size();i++)
			{
				int v = a[x][i].x;
				int w = a[x][i].w;
				if(d[x][flag]+w<d[v][flag])
				{
					d[v][flag] = d[x][flag]+w;
					q.push({v,d[v][flag],flag});
				}
			}
		}
		else
		{
			for(int i = 0;i<e[x].size();i++)
			{
				int v = e[x][i].x;
				int w = e[x][i].w;
				if(d[x][flag]+w<d[v][flag])
				{
					d[v][flag] = d[x][flag]+w;
					q.push({v,d[v][flag],flag});
				}
			}
		}
		int nflag = flag^1;
		if(d[x][nflag]>num+X)
		{
			d[x][nflag] = num+X;
			q.push({x,d[x][nflag],nflag});
		}
	}
	printf("%lld",min(d[n][0],d[n][1]));
	return 0;
}
posted @ 2025-03-02 14:20  林晋堃  阅读(273)  评论(0)    收藏  举报