CF576D Flights for Regular Customers【2019集训队作业】

CF576D Flights for Regular Customers

首先因为只有 n n n 个点,所以最多只有 n n n 个不同的 d d d

我们对每一个 d d d 从小到大来求出走 d − 1 d-1 d1 步能到达哪些点。

因为我们的 d d d 是从小到大来求的,所以对于单个 d d d 可以简单递推。

递推的过程可以用矩阵+ bitset 来加速。

#include <bits/stdc++.h>
#define N 152
#define bit bitset<N>
using namespace std;
struct edge{
	int u, v, c;
	bool operator < (edge x){
		return c < x.c;
	}
}e[N];
int n, m;
int dis[N];
bit tmp[N], mat[N];
void mul(bit *x, bit *y, bit *z){
	bit p[N];
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j)
			if(y[i][j]) p[i] |= z[j];
	for(int i = 1; i <= n; ++i) x[i] = p[i];
	return ;
}
int main(){
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= m; ++i)
		scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].c);
	sort(e + 1, e + 1 + m); mat[1][1] = 1;
	if(e[1].c != 0) return puts("Impossible"), 0;
	for(int now = 1; now <= m;){
		int pos = now;  bit p[N];
		while(e[now].c == e[pos].c && pos <= m)
			tmp[e[pos].u][e[pos].v] = 1, ++pos;
		for(int i = 1; i <= n; ++i) p[i] = tmp[i];
		queue<int> Q; memset(dis, -1, sizeof dis);
		for(int i = mat[1]._Find_first(); i <= n; i = mat[1]._Find_next(i))
			Q.push(i), dis[i] = 0;
		while(!Q.empty()){
			int u = Q.front(); Q.pop();
			for(int i = 1; i <= n; ++i)
				if(tmp[u][i] && dis[i] == -1)
					dis[i] = dis[u] + 1, Q.push(i);
		}
		if(dis[n] != -1) return printf("%d\n", e[now].c + dis[n]), 0;
		int y = max(0, e[pos].c - e[now].c);
		while(y){
			if(y & 1) mul(mat, mat, p);
			mul(p, p, p); y >>= 1;
		} now = pos;
	}
	puts("Impossible");
	return 0;
}

posted @ 2022-10-10 20:18  缙云山车神  阅读(13)  评论(0编辑  收藏  举报