• Codeforces 576D Flights for Regular Customers (图论、矩阵乘法、Bitset)


    题目链接

    http://codeforces.com/contest/576/problem/D

    题解

    把边按(t_i)从小到大排序后枚举(i), 求出按前((i-1))条边走(t_i)步能到达的点的集合,以它们为起点求(n)号点的最短路。
    前者等于前((i-2))条边走(t_{i-1})步能到达的点集乘上前((i-1))条边邻接矩阵的((t_i-t_{i-1}))次幂。
    因为只关心是否存在,故可以使用bitset优化。
    时间复杂度(O(mn^3+frac{n^3log T}{omega})).

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    inline int read()
    {
    	int x = 0,f = 1; char ch = getchar();
    	for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
    	for(;!isdigit(ch);ch=getchar()) {x = x*10+ch-48;}
    	return x*f;
    }
    
    const int N = 150;
    const int INF = 2e9;
    struct AEdge
    {
    	int u,v,t;
    	bool operator <(const AEdge &arg) const {return t<arg.t;}
    } ae[N+3];
    struct Edge
    {
    	int v,nxt;
    } e[(N<<1)+3];
    int a[N+3];
    int fe[N+3];
    int que[N+3];
    int dep[N+3];
    bool vis[N+3];
    int n,m,en;
    
    void addedge(int u,int v)
    {
    	en++; e[en].v = v;
    	e[en].nxt = fe[u]; fe[u] = en;
    }
    
    struct Matrix
    {
    	bitset<N+3> a[N+3];
    	Matrix() {for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) a[i][j] = 0;}
    	Matrix operator *(const Matrix &arg) const
    	{
    		Matrix ret;
    		for(int i=1; i<=n; i++)
    		{
    			for(int j=1; j<=n; j++)
    			{
    				if(a[i][j]) {ret.a[i]|=arg.a[j];}
    			}
    		}
    		return ret;
    	}
    };
    Matrix I,O,g,b;
    
    void clearedge()
    {
    	for(int i=1; i<=n; i++) fe[i] = 0;
    	for(int i=1; i<=en; i++) e[i].v = e[i].nxt = 0;
    	en = 0;
    }
    
    Matrix mquickpow(Matrix x,int y)
    {
    	Matrix cur = x,ret = I;
    	for(int i=0; y; i++)
    	{
    		if(y&(1<<i)) {y-=(1<<i); ret = ret*cur;}
    		cur = cur*cur;
    	}
    	return ret;
    }
    
    void bfs()
    {
    	for(int i=1; i<=n; i++) vis[i] = false;
    	int hd = 1,tl = 0;
    	for(int i=1; i<=n; i++) {if(g.a[1][i]) {tl++; que[tl] = i; vis[i] = true; dep[i] = 0;}}
    	while(hd<=tl)
    	{
    		int u = que[hd]; hd++;
    		for(int i=fe[u]; i; i=e[i].nxt)
    		{
    			int v = e[i].v;
    			if(!vis[v]) {vis[v] = true; tl++; que[tl] = v; dep[v] = dep[u]+1;}
    		}
    	}
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1; i<=n; i++) I.a[i].set(i);
    	for(int i=1; i<=m; i++)
    	{
    		scanf("%d%d%d",&ae[i].u,&ae[i].v,&ae[i].t);
    	}
    	sort(ae+1,ae+m+1);
    	g = I;
    	int ans = INF;
    	for(int i=1; i<=m; i++)
    	{
    		for(int j=1; j<=i; j++) {addedge(ae[j].u,ae[j].v);}
    		g = g*mquickpow(b,ae[i].t-ae[i-1].t);
    		bfs();
    		if(vis[n]) {ans = min(ans,ae[i].t+dep[n]);}
    		clearedge();
    		b.a[ae[i].u].set(ae[i].v);
    	}
    	if(ans==INF) puts("Impossible");
    	else printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    有趣的项目链接分享
    Nano Pi安装Opencv-python
    Opencv
    安装库的步骤
    EC20 AT指令
    最详细树莓派/NanoPi网线和电脑直接连接方法
    在Altium Designer中如何将一组器件合并为一个?
    Altium Designer如何快速查找PCB板上元件
    pip升级之后,不能使用
    利用opencv-python(cv2)查看设备连接摄像头的数量
  • 原文地址:https://www.cnblogs.com/suncongbo/p/11885356.html
Copyright © 2020-2023  润新知