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

題解 CF1407E 【Egor in the Republic of Dagestan】

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;
}