首页 > 其他分享 >AtCoder Beginner Contest 277 E // 最短路

AtCoder Beginner Contest 277 E // 最短路

时间:2022-11-14 12:22:38浏览次数:74  
标签:AtCoder dist Beginner int 短路 back heap 277 push

Crystal Switches

题目来源:AtCoder Beginner Contest 277 E - Crystal Switches

题目链接:E - Crystal Switches (atcoder.jp)


题意

给定一个\(N\)个点\(M\)条边的无向图。每条边 {\(u_i\ v_i\ a_i\)},表示\(u_i\)、\(v_i\)之间有一条初始状态为\(a_i\)的无向边,当\(a_i=1\),这条边初始可以使用,当\(a_i=0\),这条边初始不能使用。图上有\(K\)个点,结点处有开关,当位于这些结点处时,可以按下开关,使得图上所有边的状态翻转。

求:从点\(1\)到点\(N\)的最短路。

数据范围:\(1 \le N,M \le 2 \times 10^5\),\(0 \le K \le N\).

思路:最短路

考虑如何建图:

当图上开关总共按了偶数次时,初始状态为\(1\)的边是可以使用的;当图上开关总共按了奇数次时,初始状态为\(0\)的边是可以使用的。

于是,我们将每个点\(x\)拆成两个点:\(x\),开关按下了偶数次时的结点\(x\);\(x+N\),开关按下了奇数次时的结点\(x\)。

  • 对于边 {\(u\ v\ 1\)},建出边 \(u \stackrel{1}{\longleftrightarrow} v\)
  • 对于边 {\(u\ v\ 0\)},建出边 \(u+N \stackrel{1}{\longleftrightarrow} v+N\)
  • 对于有开关的结点\(s_i\),则建出边 \(s_i \stackrel{0}{\longleftrightarrow} s_i+N\)

建图之后,跑一遍起点为\(1\)的最短路,则要求的最短路就是 \(min(dist[N],dist[N+N])\).

时间复杂度:\(O((M+K)·log(M+K))\).

代码

#include <bits/stdc++.h>
#define endl '\n'
#define PII pair<int,int>
using namespace std;

const int N = 400010;
const int INF = 0x3f3f3f3f;

int n, m, k, dist[N], st[N];
vector<PII> g[N]; 

int dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, 1});

    while(heap.size()) {
        auto t = heap.top();
        heap.pop();

        int u = t.second;
        if(st[u]) continue;
        st[u] = true;

        for(auto item : g[u]) {
            int v = item.first, w = item.second;
            if(dist[v] > dist[u] + w) {
                dist[v] = dist[u] + w;
                heap.push({dist[v], v});
            }
        }
    }
    
    int res = min(dist[n], dist[n + n]);
    return res == INF ? -1 : res;
}

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> n >> m >> k;
    for(int i = 1; i <= m; ++ i) {
        int x, y, a;
        cin >> x >> y >> a;
        if(a) g[x].push_back({y, 1}), g[y].push_back({x, 1});
        else g[x + n].push_back({y + n, 1}), g[y + n].push_back({x + n, 1});
    }
    for(int i = 1; i <= k; ++ i) {
        int x;
        cin >> x;
        g[x].push_back({x + n, 0}), g[x + n].push_back({x, 0});
    }

    cout << dijkstra() << endl;

    return 0;
}

标签:AtCoder,dist,Beginner,int,短路,back,heap,277,push
From: https://www.cnblogs.com/jakon/p/16888643.html

相关文章

  • D - Takahashi's Solitaire -- ATCODER
    D-Takahashi'sSolitairehttps://atcoder.jp/contests/abc277/tasks/abc277_d 思路先计算所有的输入的和total,将输入列表首先进行排列找到所有连续段和中最大的......
  • C - Ladder Takahashi -- ATCODER
    C-LadderTakahashihttps://atcoder.jp/contests/abc277/tasks/abc277_c 思路把梯子可达楼层看成图的节点把梯子看成节点之间的连线所以整个问题变成图的遍历问题......
  • (AtCoder Beginner Contest 277)E(分层图+最短路 or bfs搜两种状态)
    E-CrystalSwitches题目大意:给你n个点,m条边,连接成一个无向图,每个边最初有一个状态(0or1)表示是否能够通过,同时给k个开关位于k的顶点上,每次点击开关会使得所有路的状......
  • ABC277E 题解
    前言题目传送门!更好的阅读体验?非常套路的分层图,纪念赛时切掉了。思路我们以样例来解释。首先,这是最基础的图。我们把图分成两层:第一层是原本\(w=1\)的路可以通......
  • ABC277D 题解
    前言题目传送门!或许更好的阅读体验?比较简单的模拟。思路首先把\(a_i\)排序。每次往后一直跑,如果不能再取了,就停下。但是这样做是\(O(n^2)\)的。我们需要优化。......
  • AtCoder Beginner Contest 277 D Takahashi's Solitaire
    Takahashi'sSolitaire双指针&&尺取先排个序,然后把数组扩展到\(2\timesn\),为了处理循环的情况然后双指针跑一下,限定\(r\)扩展的条件为:当前数字等于前一个或者......
  • AtCoder Beginner Contest 277 F Sorting a Matrix
    SortingaMatrix拓扑序首先可以明确无论怎么交换行列,原本在同一行或者同一列的元素,还是会处于同一行或者同一列条件一每行每行地看,如果能满足从小到大的条件,说明第......
  • AtCoder Beginner Contest 277 E Crystal Switches
    CrystalSwitches分层图+\(01bfs\)按钮的操作就是走分层图的边因此就构建两张图,然后将特殊点加一个双向边\(01bfs\)跑一下就行#include<iostream>#include<cstd......
  • AtCoder Beginner Contest 277 题解
    掉大分力(悲A-^{-1}直接模拟。#include<bits/stdc++.h>#defineIOSios::sync_with_stdio(false)#defineTIEcin.tie(0),cout.tie(0)#defineintlonglongusing......
  • Atcoder ARCaea 118 B
    我又来啦!光&对立题面小A正在调配药剂。传说中有一种最强的药剂,叫做Tempestissimo,用了$K$种药剂,标号$1\simK$。当时(由于这药剂只调配过一次)分别用了$......