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