1. 程式人生 > 實用技巧 >【題解】 CF1407E Egor in the Republic of Dagestan 圖論+貪心

【題解】 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;
}