首页 > 其他分享 >AT_abc277_e 题解

AT_abc277_e 题解

时间:2023-01-24 20:22:58浏览次数:39  
标签:dist int 题解 tt ++ abc277 include define

\(\mathcal Solution\)

【题意】

给定无向图,当 \(a_i = 1\) 时,该条边才能走。在给我们 \(k\) 个点,\(S_1, S_2, \cdots, S_k\),到了这些点可以选择是否取反 \((1 \to 0, 0 \to 1)\) 所有的 \(a_i\),求 \(1 \to n\) 的最短距离。

【解法】

\(dist_{i, 0}\) 表示到了 \(i\) 这个点且 \(a_i = 0\) 的边可以走的最短距离。

\(dist_{i, 1}\) 表示到了 \(i\) 这个点且 \(a_i = 1\) 的边可以走的最短距离。

则 \(dist_{i, 0} = \min\limits_{s \in g_i}\{dist_{s, 0}+1, [s \in S]dist_{s, 1} + 1\}\)。

则 \(dist_{i, 1} = \min\limits_{s \in g_i}\{dist_{s, 1}+1, [s \in S]dist_{s, 0} + 1\}\)。

其中 \(g_i\) 表示所有 \(i\) 的临边,\(S\) 表示可以取反的点。

\(dist_{i, 0}, dist_{i, 1}\) 都可以用 bfs 求得。

答案 \(= \min\{dist_{n, 0}, dist_{n, 1}\}\) 。

\(\mathcal Code\)

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <cmath>
#include <sstream>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>

#define x first
#define y second
#define IOS ios::sync_with_stdio(false)
#define cit cin.tie(0)
#define cot cout.tie(0)

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;

const int N = 200010, M = 400010, MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const LL LLINF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-8;

int n, m, k;
PII q[N * 2];
int dist[N][2];
int h[2][N], e[M], ne[M], idx;
unordered_set<int> S;

void add(int h[], int a, int b)
{
	e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

void bfs(int s)
{
	memset(dist, 0x3f, sizeof dist);

	int hh = 0, tt = -1;
	dist[s][1] = 0, q[ ++ tt] = {s, 1};
	if (S.count(1)) dist[s][0] = 0, q[ ++ tt] = {s, 0}; // 不要忘了判断 1 是否在集合中
	while (hh <= tt)
	{
		PII t = q[hh ++ ];
		int x = t.x, y = t.y;
		for (int i = h[y][x]; ~i; i = ne[i])
		{
			int j = e[i];
			if (dist[j][y] > dist[x][y] + 1) // 不懂的去看上边的思路
			{
				dist[j][y] = dist[x][y] + 1;
				q[ ++ tt] = {j, y};
			}
			if (S.count(j) && dist[j][y ^ 1] > dist[x][y] + 1)
			{
				dist[j][y ^ 1] = dist[x][y] + 1;
				q[ ++ tt] = {j, y ^ 1};
			}
		}
	}
}

void solve()
{
	memset(h, -1, sizeof h);
	
	cin >> n >> m >> k;
	while (m -- )
	{
		int a, b, c;
		cin >> a >> b >> c;
		add(h[c], a, b), add(h[c], b, a);
	}
	for (int i = 1; i <= k; i ++ )
	{
		int t;
		cin >> t;
		S.insert(t);
	}
	bfs(1);
	
	int res = min(dist[n][0], dist[n][1]); // 求答案
	if (res == INF) res = -1; // 判断无解
	cout << res << endl;
}

int main()
{
	IOS;
	cit, cot;
	int T = 1;
//	cin >> T;
	while (T -- ) solve();
	return 0;
}

标签:dist,int,题解,tt,++,abc277,include,define
From: https://www.cnblogs.com/hcywoi/p/17066334.html

相关文章

  • 2023牛客寒假算法基础集训营1 个人题解(ACDHKL)
    A.WorldFinal?WorldCup!(I)题意:给10场比赛的点球输赢情况,奇数为A队点球,偶数为B队点球思路:用两个变量x,y来分别存A队当前赢的场次和B队当前赢的场次然后就就扫......
  • CodeForces-907#B 题解
    正文设数组\(c_{x,y,i,j}\)代表\((x,y)\)位置的大格子中\((i,j)\)位置的小格子。很显然,输入中字符的输入顺序是要调整的,实际的顺序是\(x,i,y,j\)。对于输入的\(......
  • 题解
    前言只对SubTask2的选手看过来!!!很好的一道模拟题。坑点分析题目里说的很明白了:只要有\(\ge1\)个带有注释的,就是一定是祖宗人,哪怕在后面或者前面出现过符合乐子人......
  • P3802 小魔女帕琪 题解【期望dp】
    题目传送门P3802解题思路本题的解题思路关键在于分段。每一个结构段的概率在之后的结构段依然适用。判断是否符合这种特性最好方法是随机截取一段观察是否成立发现成......
  • 洛谷P3654 First Step题解
    这是一道暴力枚举。 大致题意:R行C列的棋盘要放下长度为K的线段,“#”表示无法放置,问有多少种放置方法。直接贴代码:#include<bits/stdc++.h>usingnamespacestd;i......
  • P4022 [CTSC2012]熟悉的文章 题解
    题目链接简要题意给定\(m\)个模板串和\(n\)个匹配串,如果一个字符串是一个模板串的子串且长度不小于\(L\)则称其为“熟悉的”,对于每个匹配串,求一个最大的\(L\),满足......
  • 程序员经典问题解答
    帮助在学习、上班的过程中,你是否经常遇到疑难问题无法解决,为此备受折磨?别担心,小编精选多道程序员最头痛的技术问题予以回答。QA小伙伴程序大牛C语言 Q:如何引用一个已经定义......
  • Solution 题解 UVA1389 Hard Life: 最小割,有向图,分数规划,和牛顿迭代
    题解UVA1389HardLife:最小割,有向图,分数规划,和牛顿迭代Preface黑题好耶看到了题解里面大多数是二分,我就来讲一讲简单又快速的DinkelbachAlgorithm吧!0-1分数规划......
  • 洛谷P2036 PERKET题解
     先来审题,主要有以下几个条件:酸度求乘积,苦度求和,两者相减的值最小(当然是绝对值)。下面附上AC代码:#include<bits/stdc++.h>//万能头文件usingnamespacestd;//......
  • 【题解】CF193D Two Segments
    题意给定一个\(1\simN\)的排列,在这个排列中选出两段互不重叠的区间,求使选出的元素排序后构成公差为1的等差数列的方案数。选出的两段区间中元素构成的集合相同时视为同一......