zoukankan      html  css  js  c++  java
  • CF1442C Graph Transpositions 01BFS

    题意:

    戳这里

    分析:

    • 暴力

    建分层图,直接跑最短路,把翻转次数当做最短路的状态之一,然后枚举最后的翻转状态

    • 正解

    我们发现翻转次数最劣情况下会达到 (O(n)) ,所以复杂度成了 (O(n^2))

    那么我们考虑如何优化,我们发现一个很显然的结论

    当翻转次数超过 (O(log n)) 时,翻转一次的代价远大于遍历一遍整个图

    所以我们把跑最短路时的翻转次数分成两部分,一部分是到这个点时至少翻转多少次,另一部分就是从这个点出发翻转多少次

    我们把第一部分取掉,然后最短路的状态点数就变成了 (O(18n)) 的,就可以过了

    第一部分可以 01BFS 预处理出来,最后枚举翻转了多少次

    代码:

    #include<bits/stdc++.h>
    #define pii pair<int,int>
    #define mk(x,y) make_pair(x,y)
    #define fir first
    #define sec second
    
    using namespace std;
    
    namespace zzc
    {
    	inline long long read()
    	{
    		long long x=0,f=1;char ch=getchar();
    		while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    		while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    		return x*f;
    	}
    	
    	const int maxn = 2e5+5;
    	const long long mod = 998244353;
    	const long long inf = 0x3f3f3f3f3f3f;
    	long long head[maxn],dis[maxn][20],tim[maxn],pw[1000005];
    	long long n,m,cnt=0,ans;
    	deque<long long> d;
    	queue<pii> q;
    	
    	struct edge
    	{
    		int to,nxt,dir;
    	}e[maxn<<1];
    	
    	void add(int u,int v,int w)
    	{
    		e[++cnt].to=v;
    		e[cnt].dir=w;
    		e[cnt].nxt=head[u];
    		head[u]=cnt;
    	}
    	
    	void bfs1()
    	{
    		memset(tim,0x3f,sizeof(tim));
    		d.clear();tim[1]=0;
    		d.push_front(1);
    		while(!d.empty())
    		{
    			int u=d.front();d.pop_front();
    			for(int i=head[u];i;i=e[i].nxt)
    			{
    				int v=e[i].to;
    				if(e[i].dir==(tim[u]&1))//ûÓз­×ª 
    				{
    					if(tim[v]>tim[u])
    					{
    						tim[v]=tim[u];
    						d.push_front(v);
    					}
    				}
    				else
    				{
    					if(tim[v]>tim[u]+1)
    					{
    						tim[v]=tim[u]+1;
    						d.push_back(v);
    					}
    				}
    			}
    		}
    	}
    	
    	void bfs2()
    	{
    		memset(dis,0x3f,sizeof(dis));
    		dis[1][0]=0;
    		q.push(mk(1,0));
    		while(!q.empty())
    		{
    			int u=q.front().fir,w=q.front().sec;q.pop();
    			for(int i=head[u];i;i=e[i].nxt)
    			{
    				int v=e[i].to;
    				if(w+((w&1)!=e[i].dir)>=tim[v]+20) continue;
    				if(dis[v][w+((w&1)!=e[i].dir)-tim[v]]>dis[u][w-tim[u]]+1)
    				{
    					dis[v][w+((w&1)!=e[i].dir)-tim[v]]=dis[u][w-tim[u]]+1;
    					q.push(mk(v,w+((w&1)!=e[i].dir)));
    				}
    			}
    			
    		}
    	}
    	
    	void work()
    	{
    		int a,b;
    		pw[0]=1;ans=inf;
    		for(int i=1;i<=35;i++) pw[i]=pw[i-1]*2%mod;
    		for(int i=36;i<=1000000;i++) pw[i]=pw[i-1]*2%mod;
    		n=read();m=read();
    		for(int i=1;i<=m;i++)
    		{
    			a=read();b=read();
    			add(a,b,0);add(b,a,1);
    		}
    		bfs1();
    		bfs2();
    		for(int i=0;i<=20;i++)
    		{
    			if(tim[n]+i>20&&ans!=inf) break;
    			ans=min(ans,pw[i+tim[n]]-1+dis[n][i]);
    		}
    		printf("%lld
    ",ans%mod);
    	}
    
    }
    
    int main()
    {
    	zzc::work();
    	return 0;
    }
    
    
  • 相关阅读:
    20155209林虹宇虚拟机的安装及一点Linux的学习
    预备作业2林虹宇20155209
    预备作业01:你期望的师生关系是什么?
    20155203
    我眼中的师生关系以及对于专业学习的展望
    20155319的第一次随笔
    20155336 2016-2017-2《JAVA程序设计》第二周学习总结
    20155336 2016-2017-2《JAVA程序设计》第一周学习总结
    虎光元的第三次随笔
    20155336虎光元
  • 原文地址:https://www.cnblogs.com/youth518/p/14070656.html
Copyright © 2011-2022 走看看