博客园 首页 私信博主 显示目录 隐藏目录 管理

题解 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;
}
posted @ 2020-10-18 11:12  Flash_plus  阅读(57)  评论(0编辑  收藏  举报