• 【CF827F】Dirty Arkady's Kitchen DP


    【CF827F】Dirty Arkady's Kitchen

    题意:给你一张n个点,m条边的有向图,每条边长度为1,第i条边在[li,ri)的时间内可以进入,求1到n的最短路。

    $n,mle 5 imes 10^5$

    题解:我们先将所有边按l从小到大排序,然后依次向图中加入每条边。首先对于一条边,我们可以反复走这条边,因此不难想到将每个点按到达时间的奇偶性拆成两个。然后每个点可以到达的时间就可以看成若干个互不相交的区间,我们用mn[i],mx[i]维护当前最后一段区间的左右端点。

    在加入一条边时,我们先判断当前能不能走,如果不能走我们就开个vector把每个点当前不能走的边存起来;如果能走,则我们进行BFS,取出每个点vector中的所有边并更新mn,mx值,如果一个点能走了就将其加入队列,枚举到n时更新答案即可。

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <vector>
    using namespace std;
    const int maxn=1000010;
    int n,m,tot,ans;
    int mx[maxn],mn[maxn],fir[maxn];
    struct edge
    {
    	int a,b,l,r;
    }p[maxn<<1];
    queue<int> q;
    vector<int> v[maxn];
    inline void add(int a,int b,int c,int d)
    {
    	p[++tot].a=a,p[tot].b=b,p[tot].l=c+((c^a)&1),p[tot].r=d-((d^b)&1);
    }
    bool cmp(const edge &a,const edge &b)
    {
    	return a.l<b.l;
    }
    inline void solve(int x)
    {
    	int a=p[x].a,b=p[x].b,l=p[x].l=max(p[x].l,mn[a]),r=p[x].r;
    	if(mx[a]<l)
    	{
    		v[a].push_back(x);
    		return ;
    	}
    	q.push(x);
    	while(!q.empty())
    	{
    		x=q.front(),q.pop(),a=p[x].a,b=p[x].b,l=p[x].l,r=p[x].r;
    		if(l>=r)	continue;
    		if(mx[b]+2<l)	mn[b]=l+1,mx[b]=r;
    		else	mx[b]=max(mx[b],r);
    		if((b>>1)==n)	ans=min(ans,mn[b]);
    		while(fir[b]<(int)v[b].size())
    		{
    			int t=v[b][fir[b]];
    			if(mx[b]>=p[t].l)	fir[b]++,q.push(t),p[t].l=mn[b];
    			else	break;
    		}
    	}
    }
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
    	return ret*f;
    }
    int main()
    {
    	n=rd(),m=rd();
    	if(n==1)
    	{
    		puts("0");
    		return 0;
    	}
    	int i,a,b,c,d;
    	for(i=1;i<=m;i++)
    	{
    		a=rd(),b=rd(),c=rd(),d=rd();
    		add(a<<1,b<<1|1,c,d);
    		add(a<<1|1,b<<1,c,d);
    		add(b<<1,a<<1|1,c,d);
    		add(b<<1|1,a<<1,c,d);
    	}
    	sort(p+1,p+tot+1,cmp);
    	memset(mx,0xc0,sizeof(mx)),memset(mn,0xc0,sizeof(mn));
    	mn[2]=mx[2]=0,ans=1<<30;
    	for(i=1;i<=tot;i++)	solve(i);
    	if(ans==(1<<30))	puts("-1");
    	else	printf("%d",ans);
    	return 0;
    }//5 4 1 2 0 10 2 3 0 10 3 4 0 10 4 5 0 10
  • 相关阅读:
    VMware Workstation 16.0 key (仅支持 intel 架构)
    使用思科ASA对指定端口、IP进行抓包
    轮子的意义
    dubbo学习(三)泛化
    dubbo学习(二)链接
    dubbo学习(一)线程池
    mips交叉编译:SQLite3
    生成证书脚本
    ssh连接不上 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
    gmssl ocsp 验证证书
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/8379682.html
Copyright © 2020-2023  润新知