「CF576D」 Flights for Regular Customers

「CF576D」 Flights for Regular Customers

对不起我又想网络流去了

你看这长得多像啊,走过至少多少条边就是流量下界,然后没上界

但是这个题求的最少走多少条边啊...完全不一样好吧...

然后又开始想最短路相关算法,然后觉得分层图可以直接跑,然后发现 \(d_i\le 10^9\),直接爆炸。

然后就不会了。

注意到恰好走过 \(k\) 条边的最短路是可以通过 \(\texttt{Floyd}\) 求得的。那如果我走 \(k\) 条边能够到达某个点,那么我从这个点出发一定能走到所有权值 \(\le k\) 的边上去。

这启发我们对所有边按照 \(d_i\) 从小到大排序。

然后每一次预先求出走 \(d_i\) 步能够到达的点,以这些点为起点进行 \(\texttt{BFS}\),得到的到终点的距离加上 \(d_i\) 就是可能的答案。

然后发现本题我们不需要知道最短路长度,我们只需要维护可达性,使用 \(\texttt{bitset}\) 进行优化即可。

总时间复杂度为 \(O(m\frac{n^3\log d}{w})\)

/*---Author:HenryHuang---*/
/*---Never Settle---*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=155;
int dis[maxn],n,m;
struct edge{
	int u,v,w;
	bool operator<(const edge &h)const{
		return w<h.w;
	}
}e[maxn];
struct matrix{
	bitset<maxn> a[maxn];
	matrix operator *(const matrix &h)const{
		matrix z;
		for(int i=1;i<=n;++i)
			for(int j=1;j<=n;++j)
				if(a[i][j]) z.a[i]|=h.a[j];
		return z;
	}
}ans,a;
void ksm(matrix a,int b){
	while(b){
		if(b&1) ans=ans*a;
		b>>=1,a=a*a;
	}
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=m;++i){
		int a,b,c;cin>>a>>b>>c;
		e[i]=(edge){a,b,c};
	}
	for(int i=1;i<=n;++i) ans.a[i][i]=1;
	sort(e+1,e+m+1);
	int Ans=2e9;
	for(int i=1;i<=m;++i){
		if(Ans<=e[i].w) break;
		int delta=e[i].w-e[i-1].w;
		ksm(a,delta);
		a.a[e[i].u][e[i].v]=1;
		queue<int> Q;
		for(int j=1;j<=n;++j)
			if(ans.a[1][j]) Q.emplace(j),dis[j]=0;
			else dis[j]=-1;
		while(!Q.empty()){
			int u=Q.front();Q.pop();
			for(int v=1;v<=n;++v)
				if(a.a[u][v]&&dis[v]==-1) dis[v]=dis[u]+1,Q.emplace(v);
		}
		if(dis[n]!=-1) Ans=min(Ans,dis[n]+e[i].w);
	}
	if(Ans==2e9) cout<<"Impossible\n";
	else cout<<Ans<<'\n';
	return 0;
}
posted @ 2021-02-17 19:02  Henry__Huang  阅读(59)  评论(0编辑  收藏  举报