CodeForces 682 div1 C. Graph Transpositions 最短路

题目
题意大概是:给一个有向图。每次可以执行两个操作中的任意一个:
1、 沿着边走一步 花费1s
2、 把图翻转,第一次翻转花费0秒第二次翻花费2秒第三次花费4秒……
问从1 到 n花费的最短时间。

题解

他翻转不了几次,然后就不翻转了。
但是这要怎么写呢?
一、
次数少的话可以建分层图, 很简单。
20层以后肯定是能不翻转就不翻转。
所以先建20层图,跑个最短路。如果能走到那就是最短路了。
二、
但是有那种翻转的少走不过去的样例。怎么办?
这种情况因为要取模,不能直接用距离表示。况且建不出来图。。
建两层图,一层是正的一层是反的。层与层之间边权为一个特殊值(我用的-1)距离用两个值表示:翻转的次数和走的距离。
肯定是翻转越少越好。所以优先队列先按翻转次数排。再按走的距离排。
求最短路的过程中如果遇到-1 代表翻转次数+1。

代码:

#include<stdio.h>
#include <algorithm>
#include <vector>
#include <string>
#include <math.h>
#include <queue>
#include <string.h>
#include <iostream>
// #include <unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<int,char> pic;
#define pb push_back
#define mkp make_pair
#define st first
#define sd second
// const ll INF = 0x3f3f3f3f3f3f3f;
const double esp = 1e-9;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f;
//!!!!!!!!!!!!!!!!!!!!!!!!
const int mod = 998244353;
const int maxn = 2e5 * 21;
struct Edge
{
	int id;
	ll val;
	int nex;
}edge[maxn << 1];
int cnt =0 ;
int head[maxn];
void add(int x,int y,ll val)
{
	edge[cnt].id = y;
	edge[cnt].val = val;
	edge[cnt].nex = head[x];
	head[x] = cnt ++ ;
}
int vis[maxn];
int dis[maxn];
struct cmp
{
	bool operator() (const pii& a, const pii& b)
	{
		return a.sd > b.sd;
	}
};
priority_queue<pii,std::vector<pii>,cmp> qq;
int n;
void dj1()
{
	qq.push(mkp(1,0));
	dis[1] = 0;
	while(!qq.empty())
	{
		int x = qq.top().st;
		qq.pop();
		if(vis[x])
			continue;
		vis[x] = 1;
		for(int i = head[x]; ~i; i = edge[i].nex)
		{
			int v = edge[i].id;
			if(vis[v] == 0 && dis[v] > dis[x] + edge[i].val)
			{
				dis[v] = dis[x] + edge[i].val;
				qq.push(mkp(v,dis[v])); // 脑瘫 写成了vis[v]  一直wa 
			}
		}
	}
}
pii e[maxn];

struct Node
{
	int id, c, dis;
	Node(int ii,int cc,int dd):id(ii), c(cc), dis(dd){};
	Node(){};
	bool operator < (const Node& a) const {
		if(c == a.c)
			return dis > a.dis;
		return c > a.c;
	}
};
priority_queue<Node> qt;
pii d[maxn];
void dj2()
{
	qt.push(Node(1,0,0));
	d[1] = mkp(0,0);
	while(!qt.empty())
	{
		int x = qt.top().id;
		qt.pop();
		if(vis[x])
			continue;
		vis[x] = 1;
		for (int i = head[x]; ~i; i = edge[i].nex)
		{
			int v = edge[i].id;
			int c = 0;
			int dis = 0;
			if(edge[i].val == -1)
			{
				dis = d[x].sd;
				c = d[x].st + 1;
			}
			else
			{
				dis = d[x].sd + 1;
				c = d[x].st;
			}
			if(vis[v] == 0 && d[v] > mkp(c, dis))
			{
				d[v] = mkp(c,dis);
				qt.push(Node(v,c,dis));
			}
		}
	}
}


int main()
{
	int m;
	scanf("%d%d",&n,&m);
	for (int i = 1; i <= 20 * n; i ++ )
	{
		head[i] = -1;
	}
	for (int i = 1; i <= m; i ++ )
	{
		int x, y;
		scanf("%d%d",&x,&y);
		e[i] = mkp(x,y);
	}
	int step = 19;
	for (int i = 0; i <= step; i ++ )
	{
		for (int j =  1; j <= m; j ++ )
		{
			int x = e[j].st + i * n;
			int y = e[j].sd + i * n;
			if(i & 1)
			{
				// printf("%d %d\n",y,x);
				add(y,x,1);
			}
			else
			{
				// printf("%d %d\n",x,y);
				add(x,y,1);
			}
		}
		if(i != step)
		{
			for (int j = 1; j <= n; j ++ )
			{
				int x = i * n + j;
				int y = (i + 1) * n + j;
				// printf("%d %d %d\n",x,y,1 << i);
				add(x,y,1 << i);
			}
		}
	}

	/*
	init
	*/
	for (int i = 1; i <= 20 * n; i ++ )
	{
		dis[i] = INF;
		vis[i] = 0;
	}
	dj1();
	int ans = INF;
	for (int  i= 0; i <= step ;i ++ )
	{
		int x = (i + 1) * n;
		// printf("%d %lld 1111111\n",x,dis[x]);
		ans = min(ans,dis[x]);
	}
	// printf("%lld\n",ans);
	if(ans != INF)
	{
		printf("%d\n",ans);
		return 0;
	}
	cnt = 0;
	for (int i = 1; i <= 2 * n; i ++ )
	{
		vis[i] = 0;
		d[i] = mkp(inf,inf);
		head[i] = -1;
	}
	for (int i = 1; i<= m; i ++ )
	{
		int x = e[i].st;
		int y = e[i].sd;
		add(x, y, 1);
		add(y + n, x + n, 1);
	}
	for (int i = 1; i<= n; i ++ )
	{
		add(i,i + n, -1);
		add(i + n, i, -1);
	}
	dj2();
	pii t = mkp(inf,inf);
	for (int i = 0; i <= 1; i ++ )
	{
		int x = (i + 1) * n;
		t = min(t,d[x]);
	}
	// printf("%d %lld\n",t.st,t.sd);
	ll s=  1;
	ll sum = 0;
	for (int  i= 1; i <= t.st; i ++ )
	{
		sum = sum + s;
		sum %= mod;
		s <<= 1;
		s %= mod;
	}
	sum = (sum + t.sd) % mod;
	printf("%lld\n",sum);

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一章:大数据与云计算 1.何为大数据? 海量数据或巨量数据,其规模巨大到无法通过目前主流的计算机系统在合理时间内获取、存储、管理、处理并提炼以帮助使用者决策。 2.大数据具有4V+1C的特征 (1)数据量大:存储的数据量巨大,PB级是常态 (2)多样:数据的来源及格式多样 (3)快速:数据增长速度快 (4)价值密度低:需要对大量的数据进行处理,挖掘其潜在的价值。 (5)复杂度:对数据的处理和分析的难度大 3.什么是云计算? 长定义:云计算是一种商业模型。它将计算任务分布在大量计算机构成的资源池上,使各种应用系统能根据需要获取计算力、存储空间和信息服务。 短定义:云计算是通过网络按需提供可动态伸缩的廉价计算服务。 4.云计算是并行计算、分布式计算和网络计算的发展。 5.云计算特点: (1)超大规模(2)虚拟化(3)高可靠性(4)通用性 (5)高可伸缩性(6)按需服务(7)极其廉价 6.云计算按照服务类型大致可分为三类 (1)将基础设施作为服务。(IaaS)(2)将平台作为服务。(PaaS)(3)将软件作为服务(SaaS) 7.云计算实现机制 云计算技术体系结构分为四层:物理资源层、资源池层、管理中间件层和SOA构建层 8.云计算优势 (1)更低的硬件和网络成本(2)更低的管理成本和电力成本(3)更高的资源利用率
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值