【题解】 CF1407E Egor in the Republic of Dagestan 图论+贪心

Legend

Link \(\textrm{to Codeforces}\)

给定 \(n\ (1 \le 500\ 000)\) 个点,\(m \ (0 \le m \le 500\ 000)\) 条有向边,每条边为两种颜色之一。

你需要给点染色,点染色后只能走颜色相同的出边。找到一种染色方案使得 \(1\to n\) 最短路最长。

Editorial

这题很容易让人想成 \(\textrm{dp}\)

你发现设 \(\textrm{dp}\) 的时候总是想带着一个维度:点的颜色

点的颜色真的这么恶心吗?

算是个套路吧,建一个反图,那么这条边和它的终点的颜色就会是相同的,我们就不需要理会点的颜色了。

我们把每一个点 \(\textrm{bfs}\) 到第二种不同的颜色的时候才更新路径长度即可。

Code

#include <bits/stdc++.h>

using namespace std;
const int MX = 5e5 + 233;

int head[MX] ,tot;
struct edge{int node ,next ,w;}h[MX];

void addedge(int u ,int v ,int w){h[++tot] = (edge){v ,head[u] ,w} ,head[u] = tot;}

int vis[MX] ,color[MX];
int dis[MX] ,n ,m;

void bfs(){
	queue<int> q;
	q.push(n);
	dis[1] = -1;
	dis[n] = 0;
	while(!q.empty()){
		int x = q.front(); q.pop();
		for(int i = head[x] ,d ; i ; i = h[i].next){
			d = h[i].node;
			if(vis[d] == 3) continue;
			vis[d] |= 1 << h[i].w;
			if(vis[d] == 3){
				q.push(d);
				dis[d] = dis[x] + 1;
			}else{
				color[d] = h[i].w ^ 1;
			}
		}
	}
}

int read(){
	char k = getchar(); int x = 0;
	while(k < '0' || k > '9') k = getchar();
	while(k >= '0' && k <= '9')
		x = x * 10 + k - '0' ,k = getchar();
	return x;
}

int main(){
	cin >> n >> m;
	for(int i = 1 ,u ,v ,w ; i <= m ; ++i){
		u = read() ,v = read() ,w = read();
		addedge(v ,u ,w);
	}
	bfs();
	cout << dis[1] << endl;
	for(int i = 1 ; i <= n ; ++i)
		putchar(color[i] + '0');
	return 0;
}
posted @ 2020-09-16 19:51  Imakf  阅读(187)  评论(0编辑  收藏  举报