CF1407E Egor in the Republic of Dagestan 题解

89 篇文章 1 订阅

这是一题dp题。

首先要先去除自环,因为要走最短路,这个肯定没有意义。

d p i , c o l dp_{i,col} dpi,col表示第 i i i个点涂上 c o l col col这个颜色走到终点最短路最长是多少。

转移也非常好想: d p i , c o l = min ⁡ { max ⁡ ( d p j , 0 , d p j , 1 ) + 1 } , ( e d g e { i , j , c o l } ∈ E ) dp_{i,col}=\min \{\max(dp_{j,0},dp_{j,1})+1\},(edge\{i,j,col\}\in \mathbb{E} ) dpi,col=min{max(dpj,0,dpj,1)+1},(edge{i,j,col}E)

肯定是小的更新大的,所以最短路转移就好了。

另外,由于 d p j , 0 与 d p j , 1 dp_{j,0}与dp_{j,1} dpj,0dpj,1取了一个 max ⁡ \max max,所以如果用 j j j来更新 i i i的化,必须是第二个出现的。我们可以记录一个 c n t cnt cnt

初始化 d p n , 0 = d p n , 1 = 0 dp_{n,0}=dp_{n,1}=0 dpn,0=dpn,1=0

答案 = max ⁡ ( d p 1 , 0 , d p 1 , 1 ) =\max(dp_{1,0},dp_{1,1}) =max(dp1,0,dp1,1)

最后考虑第 i i i个点。

  1. d p i , 0 > d p i , 1 , c o l i = 0 dp_{i,0}>dp_{i,1},col_i=0 dpi,0>dpi,1,coli=0
  2. d p i , 0 < d p i , 1 , c o l i = 1 dp_{i,0}<dp_{i,1},col_i=1 dpi,0<dpi,1,coli=1

Code

/*
{By GWj
*/
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define R(a) cin>>a
#define R2(a,b) cin>>a>>b
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MAXN=5e5+20;
vector<pair<int,bool > > g[MAXN];
void add_edge(int u,int v,int col){
	if(u==v) return ;
	g[v].PB(II(u,col));
}
int n,m;
int dp[MAXN][2];
int cnt[MAXN];
int main(){
	fastio;
	R2(n,m);
	rb(i,1,m){
		int u,v,c;
		cin>>u>>v>>c;
		add_edge(u,v,c); 
	} 
	memset(dp,63,sizeof(dp));
	dp[n][0]=dp[n][1]=0;
	priority_queue<pair<int,mp> ,vector<pair<int,mp> > ,greater<pair<int,mp> > > q;
	q.push(II(0,II(n,0)));
	q.push(II(0,II(n,1)));
	while(!q.empty()){
		pair<int,mp> now=q.top();
		q.pop();
		int i,j;
		i=now.SEC.FIR;
		j=now.SEC.SEC;
		if(dp[i][j]!=now.FIR) continue;
		cnt[i]++;
		if(cnt[i]==1) continue;
		for(auto it:g[i]){
			if(dp[it.FIR][it.SEC]>dp[i][j]+1){
				dp[it.FIR][it.SEC]=dp[i][j]+1;
				q.push(II(dp[it.FIR][it.SEC],II(it.FIR,it.SEC)));
			}
		}
	}
	cout<<(max(dp[1][0],dp[1][1])!=INF? max(dp[1][0],dp[1][1]):-1)<<endl;
	rb(i,1,n){
		cout<<(dp[i][1]>dp[i][0]? 1:0);
	}cout<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值