【題解】 CF1407E Egor in the Republic of Dagestan 圖論+貪心
阿新 • • 發佈:2020-09-16
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; }