CF576 D Flights for Regular Customers (矩乘)

题意

一张n个点,m条边的有向图,你要从1到n。每条边有一个限制x表示,要使用这条边你必须先经过了x条边。求最短路。

n , m 150 , x 1 e 9 n,m\leq150,x\leq1e9

思路

  • 将边排序,然后枚举最终需要使用(而不是可以使用)的边集,首先考虑如何让选中的所有边可行。
  • F [ i ] F[i] 表示走到 i i 并且恰好解锁当前边是否可行。发现在这条边可用前,可用边集是不变的。
  • 于是可以使用上一条加入边集的边的 F F 来更新这一次的 F F
  • 这里需要用到矩阵快速幂来加速,并且还要使用bitset优化。
  • 把当前的可行图跑一个floyd。再枚举解锁所有选中边的点,计算长度即可。
  • O ( m n 3 / w log ( d ) ) O(mn^3/w\log(d)) ,CF 4s足够通过本题。
#include <bits/stdc++.h>
using namespace std;
const int N = 160, inf = 1e9 + N;
int n, m;
bool a[N][N], b[N][N], lasb[N][N];
int f[N][N];
pair<int, pair<int,int> > edge[N];
int ans = inf;
bitset<N> ar[N], br[N];
void mult(const bool a[N][N], const bool b[N][N], bool c[N][N]) {
	for(int i = 1; i <= n; i++) {
		ar[i].reset();
		for(int j = 1; j <= n; j++) {
			ar[i][j] = a[i][j];
		}
	}

	for(int j = 1; j <= n; j++) {
		br[j].reset();
		for(int i = 1; i <= n; i++) {
			br[j][i] = b[i][j];
		}
	}

	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			c[i][j] = (ar[i] & br[j]).any();
		}
	}
}

void ksm(const bool a[N][N], int y, bool c[N][N]) {
	static bool f[N][N];
	memcpy(f, a, sizeof f);
	for(; y; y>>=1) {
		if (y & 1) mult(c, f, c);
		mult(f, f, f);
	}
}

int main() {
	freopen("d.in","r",stdin);
	cin>>n>>m;
	for(int i = 1; i <= m; i++) {
		int u, v, d; scanf("%d %d %d",&u,&v,&d);
		edge[i] = make_pair(d, make_pair(u, v));
	}
	sort(edge + 1, edge + 1 + m);
	b[1][1] = 1;
	for(int e = 1; e <= m; e++) {
		ksm(a, edge[e].first - edge[e - 1].first, b);
		a[edge[e].second.first][edge[e].second.second] = 1;
		for(int i = 1; i <= n; i++) {
			for(int j = 1; j <= n; j++) if (a[i][j]) {
				f[i][j] = 1;
			} else f[i][j] = inf;
		}
		for(int k = 1; k <= n; k++) {
			for(int i = 1; i <= n; i++) if (i != k) {
				for(int j = 1; j <= n; j++) if (i != j && j != k) {
					f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
				}
			}
		}
		for(int i = 1; i <= n; i++) if (b[1][i]) {
			ans = min(ans, edge[e].first + f[i][n]);
		}
	}
	if (ans == inf) {
		printf("Impossible\n");
	} else printf("%d\n", ans);
}

发布了266 篇原创文章 · 获赞 93 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/jokerwyt/article/details/102830795
今日推荐