題解 CF1407E 【Egor in the Republic of Dagestan】
阿新 • • 發佈:2020-10-18
CF1407E 題解
題目大意
有一張圖,每條邊都有一個權值 \(0/1\) 。
你現在需要給點染色 \(0/1\) ,一條邊可以經過有且僅當它的起始點的顏色和邊的顏色一樣。
問你可不可以使得從 \(1 \to n\) 不存在連通的路徑,如果不可以,求最短路徑,路徑長度定義為這條路徑上邊的數量。
題解
這題作為 \(2E\) 來說還是挺簡單的,算是白給吧。
你考慮一條邊什麼時候才可以連通,這是取決於它的前一個點。
但是如果你正序的去遍歷的話,你肯定會先遍歷到它的起始點,但是這個點可能和多個邊對應,那怎麼處理?
那我們就反著來!!
從 \(n\) 號點開始遍歷,如果當前的 \(2\) 點之間只有一種顏色的邊,表示你可以把這條路堵死,那就把它堵死。
如果有 \(2\) 種顏色,那麼他的節點也就不是什麼很重要的問題了。
你會說一個節點會連線多條邊,為什麼對其他的邊沒有影響呢?
因為我們做的是 \(BFS\) 每個節點只要統計最短的路徑,而且每次先被遍歷到的一定比下一次遍歷到的路徑要短,所以直接 \(BFS\) 就可以了。
#include <iostream> #include <queue> #include <string.h> #include <stdio.h> using namespace std; const int maxn = 5e5 + 10; int n, m, x, y, w, cnt, col[maxn], dis[maxn], vis[maxn], d[maxn], head[maxn]; struct node { int nxt, to, val; } e[maxn << 1]; void add(int x, int y, int w) { e[++ cnt].to = y; e[cnt].nxt = head[x]; head[x] = cnt; e[cnt].val = w; } queue<int>q; int main() { // cin >> n >> m; scanf("%d%d", &n, &m); for(int i = 1; i <= m; ++ i) { // cin >> x >> y >> w; scanf("%d%d%d", &x, &y, &w); add(y, x, w); } if(n == 1) { cout << "0" << endl << "0"; return 0; } memset(col, -1, sizeof(col)); q.push(n); vis[n] = 0; while(q.size()) { int x = q.front(); q.pop(); if(x == 1) { break; } for(int i = head[x]; i; i = e[i].nxt) { int v = e[i].to; if(vis[v]) continue; if(col[v] == -1 || col[v] == 1 - e[i].val) { col[v] = 1 - e[i].val; } else { q.push(v); d[v] = d[x] + 1; vis[v] = 1; } } } if(d[1]) { cout << d[1] << endl; } else { cout << "-1" << endl; } for(int i = 1; i <= n; ++ i) { if(col[i] == -1) { cout << "0"; } else { cout << col[i]; } } return 0; }