zoukankan      html  css  js  c++  java
  • Codeforces 536D. Tavas in Kansas 题解

    题目链接:D. Tavas in Kansas

    题目大意:洛谷


    题解:首先肯定是以(s,t)为原点跑最短路,然后 DP,这很显然。

    然而,如果直接做的话十分麻烦(写得头晕脑胀还放弃了)。

    但是,如果我们对距离离散化一下,然后对于每一个点考虑它在二维平面上的坐标是((disS_i,disT_i)),问题就转化为了两条直线,一开始分别是(x=0,y=0),然后轮流平移,直接 DP 即可。

    时间复杂度(O(n^2))

    代码:

    #include <cstdio>
    template<typename Elem>
    void read(Elem &a){
    	a=0;
    	char c=getchar();
    	int f=1;
    	while(c<'0'||c>'9'){
    		if(c=='-'){
    			f=-1;
    		}
    		c=getchar();
    	}
    	while(c>='0'&&c<='9'){
    		a=(a<<1)+(a<<3)+(c^48);
    		c=getchar();
    	}
    	if(f==-1){
    		a=-a;
    	}
    }
    template<typename Elem>
    Elem abs(Elem a){
    	return a<0?-a:a;
    }
    template<typename Elem>
    void swap(Elem& a,Elem& b){
    	Elem t=a;
    	a=b;
    	b=t;
    }
    const int Maxn=100000;
    const int Mod=1000000007;
    int id[Maxn+5],sign[Maxn+5],deg[Maxn+5],vis[Maxn+5];
    int head[Maxn+5],arrive[Maxn<<1|5],nxt[Maxn<<1|5],val[Maxn<<1|5],tot;
    int num[Maxn+5];
    void unuse_add_edge(int from,int to,int w){
    	arrive[++tot]=to;
    	nxt[tot]=head[from];
    	val[tot]=w;
    	head[from]=tot;
    }
    void add_edge(int u,int v,int w){
    	unuse_add_edge(u,v,w);
    	unuse_add_edge(v,u,w);
    	deg[u]++;
    	deg[v]++;
    }
    int rev[Maxn+5];
    int sta[Maxn+5];
    int top;
    void dfs(int u){
    	sta[++top]=u;
    	vis[u]=1;
    	for(int i=head[u];i;i=nxt[i]){
    		int v=arrive[i];
    		if(vis[v]){
    			continue;
    		}
    		rev[top]=val[i];
    		dfs(v);
    	}
    }
    int res[2];
    int main(){
    	int n,m;
    	read(m),read(n);
    	int c_0=0,c_1=0;
    	for(int i=1;i<=m;i++){
    		int k,x,y;
    		read(k);
    		if(k==2){
    			read(x),read(y);
    		}
    		else{
    			read(x);
    		}
    		num[i]=k;
    		if(k==2){
    			if(x==y){
    				c_0++;
    				vis[i]=1;
    				id[abs(x)]=i;
    				continue;
    			}
    			if(x==-y){
    				c_1++;
    				vis[i]=1;
    				id[abs(x)]=i;
    				continue;
    			}
    		}
    		if(id[abs(x)]){
    			add_edge(i,id[abs(x)],(x<0)^sign[abs(x)]);
    		}
    		else{
    			id[abs(x)]=i;
    			sign[abs(x)]=(x<0);
    		}
    		if(k==2){
    			if(id[abs(y)]){
    				add_edge(i,id[abs(y)],(y<0)^sign[abs(y)]);
    			}
    			else{
    				id[abs(y)]=i;
    				sign[abs(y)]=(y<0);
    			}
    		}
    	}
    	res[0]=1;
    	while(c_0--){
    		res[0]=res[1]=(res[0]+res[1])%Mod;
    	}
    	while(c_1--){
    		res[0]=(res[0]<<1)%Mod;
    		res[1]=(res[1]<<1)%Mod;
    		swap(res[0],res[1]);
    	}
    	int mul=1;
    	for(int i=1;i<=n;i++){
    		if(!id[i]){
    			mul=(mul<<1)%Mod;
    		}
    	}
    	for(int i=1;i<=m;i++){
    		if(vis[i]){
    			continue;
    		}
    		if(!deg[i]){
    			vis[i]=1;
    			if(num[i]==1){
    				res[0]=res[1]=(res[0]+res[1])%Mod;
    			}
    			else{
    				int tr_0=(res[0]+3ll*res[1])%Mod;
    				int tr_1=(3ll*res[0]+res[1])%Mod;
    				res[0]=tr_0;
    				res[1]=tr_1;
    			}
    		}
    		if(deg[i]==1){
    			top=0;
    			dfs(i);
    			int r_0=1,r_1=0,r_2=0,r_3=0;
    			if(num[sta[1]]==2){
    				r_2=1;
    			}
    			for(int j=1;j<top;j++){
    				int tr_0,tr_1,tr_2,tr_3;
    				if(rev[j]){
    					tr_0=(r_1+r_3)%Mod;
    					tr_1=(r_0+r_2)%Mod;
    					tr_2=(r_0+r_3)%Mod;
    					tr_3=(r_1+r_2)%Mod;
    				}
    				else{
    					tr_0=(r_0+r_3)%Mod;
    					tr_1=(r_1+r_2)%Mod;
    					tr_2=(r_1+r_3)%Mod;
    					tr_3=(r_0+r_2)%Mod;
    				}
    				r_0=tr_0;
    				r_1=tr_1;
    				r_2=tr_2;
    				r_3=tr_3;
    			}
    			if(num[sta[top]]==2){
    				r_2=(r_2+(r_0+r_2)%Mod)%Mod;
    				r_3=(r_3+(r_1+r_3)%Mod)%Mod;
    			}
    			r_0=(r_0+r_3)%Mod;
    			r_1=(r_1+r_2)%Mod;
    			int tr_0=(1ll*r_0*res[0]+1ll*r_1*res[1])%Mod;
    			int tr_1=(1ll*r_1*res[0]+1ll*r_0*res[1])%Mod;
    			res[0]=tr_0;
    			res[1]=tr_1;
    		}
    	}
    	for(int i=1;i<=m;i++){
    		if(vis[i]){
    			continue;
    		}
    		top=0;
    		dfs(i);
    		int R_0=0,R_1=0;
    		int r_0,r_1,r_2,r_3;
    		int Val=0;
    		for(int j=head[sta[1]];j;j=nxt[j]){
    			int v=arrive[j];
    			if(v==sta[top]){
    				Val=val[j];
    			}
    		}
    		r_0=1;
    		r_1=r_2=r_3=0;
    		for(int j=1;j<top;j++){
    			int tr_0,tr_1,tr_2,tr_3;
    			if(rev[j]){
    				tr_0=(r_1+r_3)%Mod;
    				tr_1=(r_0+r_2)%Mod;
    				tr_2=(r_0+r_3)%Mod;
    				tr_3=(r_1+r_2)%Mod;
    			}
    			else{
    				tr_0=(r_0+r_3)%Mod;
    				tr_1=(r_1+r_2)%Mod;
    				tr_2=(r_1+r_3)%Mod;
    				tr_3=(r_0+r_2)%Mod;
    			}
    			r_0=tr_0;
    			r_1=tr_1;
    			r_2=tr_2;
    			r_3=tr_3;
    		}
    		if(Val){
    			R_0=(r_1+r_3)%Mod;
    			R_1=(r_0+r_2)%Mod;
    		}
    		else{
    			R_0=(r_0+r_3)%Mod;
    			R_1=(r_1+r_2)%Mod;
    		}
    		r_0=r_1=r_3=0;
    		r_2=1;
    		for(int j=1;j<top;j++){
    			int tr_0,tr_1,tr_2,tr_3;
    			if(rev[j]){
    				tr_0=(r_1+r_3)%Mod;
    				tr_1=(r_0+r_2)%Mod;
    				tr_2=(r_0+r_3)%Mod;
    				tr_3=(r_1+r_2)%Mod;
    			}
    			else{
    				tr_0=(r_0+r_3)%Mod;
    				tr_1=(r_1+r_2)%Mod;
    				tr_2=(r_1+r_3)%Mod;
    				tr_3=(r_0+r_2)%Mod;
    			}
    			r_0=tr_0;
    			r_1=tr_1;
    			r_2=tr_2;
    			r_3=tr_3;
    		}
    		if(Val){
    			R_0=(R_0+(r_0+r_3)%Mod)%Mod;
    			R_1=(R_1+(r_1+r_2)%Mod)%Mod;
    		}
    		else{
    			R_0=(R_0+(r_1+r_3)%Mod)%Mod;
    			R_1=(R_1+(r_0+r_2)%Mod)%Mod;
    		}
    		int tr_0=(1ll*R_0*res[0]+1ll*R_1*res[1])%Mod;
    		int tr_1=(1ll*R_1*res[0]+1ll*R_0*res[1])%Mod;
    		res[0]=tr_0;
    		res[1]=tr_1;
    	}
    	printf("%d
    ",(int)(1ll*res[1]*mul%Mod));
    	return 0;
    }
    
    本博客欢迎转载,转载请注明文章出处作者
  • 相关阅读:
    NOIP2006代码及简析
    设计模式的原则
    UML应用
    关系
    活动图
    状态图
    UML概序
    UML基本图示
    用例
    介绍一个好的英语学习网站!
  • 原文地址:https://www.cnblogs.com/withhope/p/13547543.html
Copyright © 2011-2022 走看看