首页 > 其他分享 >(AtCoder Beginner Contest 277)E(分层图+最短路 or bfs搜两种状态)

(AtCoder Beginner Contest 277)E(分层图+最短路 or bfs搜两种状态)

时间:2022-11-13 20:46:45浏览次数:63  
标签:AtCoder Beginner Contest int back mk dix st2 push

E - Crystal Switches


题目大意:

给你n个点,m条边,连接成一个无向图,每个边最初有一个状态(0 or 1)表示是否能够通过,同时给k个开关位于k的顶点上,每次点击开关会使得所有路的状态发生改变,问从1到n的最短路径。


解题思路:

  1. 分层图
    看见一个图有多种状态就可以想到经典的分层图模型,个人感觉分层图和扩展域并查集有点像,都是通过扩展集合来维护多种状态之间的关系。
    分层图:
	for (int i = 1; i <= m; ++i) {
		int a, b, c;
		cin >> a >> b >> c;
		if (c) {
			e[a].push_back(mk_p(b, c));//状态1的路径在同一层[1,n]
			e[b].push_back(mk_p(a, c));
		} else {//状态0的路径在同一层[1+n,n+n]
			e[a+n].push_back(mk_p(b+n, c^1));
			e[b+n].push_back(mk_p(a+n, c^1));
		}
	}
	
	for(int i = 1;i <= k;++i)//开关,连接两种状态的通道
        {
		int x;
		cin>>x;
		e[x].push_back(mk_p(x+n,0));//连接状态1和状态0的路径
		e[x+n].push_back(mk_p(x,0));
	}

将不同状态分层并添加在两种状态之间转换的路径

  1. bfs+两种状态搜索:
    通过搜索相同状态来转移最短路,在开关节点处要注意同时考虑0,1两种状态
    剩下的就和最短路差不多了

代码实现:

  1. 分层图
#include<bits/stdc++.h>
using namespace std;
# define int long long
# define endl "\n"
# define mk_p(a,b) make_pair(a,b)
const int N = 2e5 + 10, inf = 0x3f3f3f3f;
typedef pair<int, int> node;
vector<node> e[N<<1];
int dix[N<<1];
int vis[N<<1];
int n, m, k;
void dijstra(int st){
	for(int i = 1;i <= 2*n;++i){
		dix[i] = inf;
		vis[i] = 0;
	}
	priority_queue<node,vector<node>,greater<node> > q;
	q.push(mk_p(-inf,st));
	dix[st] = 0;
	while(!q.empty()){
		int u = q.top().second;
		q.pop();
		if(vis[u]) continue;
		vis[u] = 1;
		for(auto [v,w]:e[u]){
			if(dix[v]>dix[u]+w){
				dix[v] = dix[u]+w;
				q.push(mk_p(dix[v],v));
			}
		}
	}
}


void solve() {

	cin >> n >> m >> k;
	for (int i = 1; i <= m; ++i) {
		int a, b, c;
		cin >> a >> b >> c;
		if (c) {
			e[a].push_back(mk_p(b, c));
			e[b].push_back(mk_p(a, c));
		} else {
			e[a+n].push_back(mk_p(b+n, c^1));
			e[b+n].push_back(mk_p(a+n, c^1));
		}
	}
	
	for(int i = 1;i <= k;++i){
		int x;
		cin>>x;
		e[x].push_back(mk_p(x+n,0));
		e[x+n].push_back(mk_p(x,0));
	}
	
	dijstra(1);
	
	if(dix[n]==inf && dix[2*n] == inf) cout<<-1<<endl;
	else cout<<min(dix[n],dix[2*n])<<endl;


}
int tt;
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	tt = 1;
//	cin >> tt;
	while (tt--) solve();


	return 0;
}
  1. bfs
# include<iostream>
# include<bits/stdc++.h>
using namespace std;
# define int long long
# define endl "\n"
const int N = 5e5 + 10, inf = 0x3f3f3f3f;
typedef pair<int, int> node;
# define mk_p(a,b) make_pair(a,b)
vector<node> e[N];
int dix[N][2];//dix[u][0],dix[u][1]表示在两种状态下的最短路
int a[N];//开关
void solve() {
	int n, m, k;
	cin >> n >> m >> k;
	for (int i = 1; i <= m; ++i) {
		int a, b, c;
		cin >> a >> b >> c;
		e[a].push_back(mk_p(b, c));
		e[b].push_back(mk_p(a, c));
	}
	for (int i = 1; i <= k; ++i) {
		int x;
		cin >> x;
		a[x]  = 1;
	}
	queue<node> q;
	q.push(mk_p(1, 1));
	memset(dix, 0x3f, sizeof dix);
	dix[1][1] = 0;

	while (!q.empty()) {
		int u = q.front().first;
		int st = q.front().second;
		q.pop();
		if (!a[u]) {
			for (auto [v, st2] : e[u]) {
				if (st2 != st) continue;
				if (dix[v][st2] > dix[u][st] + 1) {
					dix[v][st2] = dix[u][st] + 1;
					q.push(mk_p(v, st2));
				}
			}
		} else {
			for (auto [v, st2] : e[u]) {
				if (st2 != st) {
					if (dix[v][st2] > dix[u][st] + 1) {
						dix[v][st2] = dix[u][st] + 1;
						q.push(mk_p(v, st2));
					}
				} else if (dix[v][st2] > dix[u][st] + 1) {
					dix[v][st2] = dix[u][st] + 1;
					q.push(mk_p(v, st2));
				}
			}
		}
	}

	int minn = inf;
	if (dix[n][0] != -1) minn = min(dix[n][0], minn);
	if (dix[n][1] != -1) minn = min(dix[n][1], minn);
	if (minn == inf)cout << -1 << endl;
	else cout << minn << endl;
}
int tt;
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	tt = 1;
//	cin >> tt;
	while (tt--) solve();


	return 0;
}

标签:AtCoder,Beginner,Contest,int,back,mk,dix,st2,push
From: https://www.cnblogs.com/empty-y/p/16886860.html

相关文章

  • 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......
  • Weekly Contest 317
    WeeklyContest317ProblemAAverageValueofEvenNumbersThatAreDivisiblebyThree思路事实上就是求整除6的数的均值代码classSolution:defaverageVal......
  • Atcoder ARCaea 118 B
    我又来啦!光&对立题面小A正在调配药剂。传说中有一种最强的药剂,叫做Tempestissimo,用了$K$种药剂,标号$1\simK$。当时(由于这药剂只调配过一次)分别用了$......
  • 塔防(cover)Atcoder/Codeforces的某道题
    题目背景在某个塔防游戏中,有一种防御塔,可以攻击到上下左右四个方向以及自身位置的敌人。题目描述塔防游戏的⼀个关卡地图可以看作⼀个的矩阵,也就是⾏,列的矩阵。其......
  • AtCoder Regular Contest 149 D Simultaneous Sugoroku
    很妙的一个题。没法用数据结构直接维护点的移动。可以挖掘一些性质。发现对于两个点\(x\)和\(-x\),它们的移动关于原点对称。可以根据对称性维护森林。维护当前的区间......
  • atcoder abc 276
    A-Rightmost题意:给定一个字符串,确定字母a,最后出现的位置,若字符串中没有出现字母a,则输出-1思路:遍历统计代码:#include<bits/stdc++.h>usingnamespacestd;int......
  • Team Weekly Contest 2022-11-06
    2022ICPCAsiaTaiwanOnlineProgrammingContestH.Heximal不会高精度,拿python写的,但是python3.8会TLE,python2不会,就是有点卡高精度+快速幂deffp(x,y):ret=......