zoukankan      html  css  js  c++  java
  • P2151 [SDOI2009]HH去散步

    Aimee

    首先的问题,如果这个题是无向图怎么搞,显然dp[i][j]表示到点i走了j步就可以了。

    但是这是无向图啊,怎么搞呢

    那就统计一下从那条边来的,也就是i表示从i边结束

    然后暴力转移显然,但是tle起飞

    显然可以用矩阵优化一下。

    下标很重要,因为矩阵乘法的美妙性质。

    最后的统计的时候正难则反,统计反向的边。

    结构体是个好东西,妥善利用起来,还有重载,减少码量。

    更详细的题解

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int n,m,t,S,T;
    int mod=45989;
    int x,y;
    struct edge{
    	int to;
    	int f;
    	int ne;
    }ed[150];
    int head[60];
    int p=0;
    int ans[160][160];
    int l;
    int tem[160][160];
    int fa[160][160];
    int org[160][160];
    void power(int n){
    	while(n){
    		if(n&1){
    			for(int i=1;i<=l;++i){
    				for(int j=1;j<=l;++j){
    					tem[i][j]=0;
    					for(int k=1;k<=l;++k){
    						tem[i][j]+=org[i][k]*ans[k][j];
    						tem[i][j]%=mod;
    					}
    				}
    			}
    			for(int i=1;i<=l;++i){
    				for(int j=1;j<=l;++j){
    					ans[i][j]=tem[i][j];
    				}
    			}
    		}
    		n>>=1;
    		for(int i=1;i<=l;++i){
    			for(int j=1;j<=l;++j){
    				tem[i][j]=0;
    				for(int k=1;k<=l;++k){
    					tem[i][j]+=org[i][k]*org[k][j];
    					tem[i][j]%=mod;
    				}
    			}
    		}
    		for(int i=1;i<=l;++i){
    			for(int j=1;j<=l;++j){
    				org[i][j]=tem[i][j];
    			}
    		}
    	}
    	return ;
    }
    int op(int x){
    	return (x&1) ?x+1:x-1;
    }
    int znx;
    void add(int f,int to){
    	ed[++p].f=f;
    	ed[p].to=to;
    	ed[p].ne=head[f];
    	head[f]=p;
    }
    signed main(){
    	scanf("%d%d%d%d%d",&n,&m,&t,&S,&T);
    	S++;
    	T++;
    	for(int i=1;i<=m;++i){
    		scanf("%d%d",&x,&y);
    		x++;
    		y++;
    		add(x,y);
    		add(y,x);
    	}
    	for(int i=1;i<=p;++i){
    		for(int  k=head[ed[i].to];k;k=ed[k].ne){
    			if(k!=op(i)){
    				org[k][i]++;
    			}
    		}	
    	}
    	l=p;
    	for(int i=1;i<=p;++i){
    		ans[i][i]=1;
    	}
    	for(int i=head[S];i;i=ed[i].ne){
    		fa[i][1]++;
    	}
    	power(t-1);
    	for(int i=1;i<=l;++i){
    			for(int j=1;j<=l;++j){
    				tem[i][j]=0;
    				for(int k=1;k<=l;++k){
    					tem[i][j]+=ans[i][k]*fa[k][j];
    					tem[i][j]%=mod;
    				}
    			}
    		}
    	for(int i=head[T];i;i=ed[i].ne){
    		znx=(znx+tem[op(i)][1])%45989;
    	}
    	cout<<znx;
    	return 0;
    } 
    
  • 相关阅读:
    PAT 2016 数据的交换输出
    HDU 2020 绝对值排序
    HDU 2013 蟠桃记
    HDU 2005 第几天?
    HDU 2004 成绩转换
    系统时钟初始化
    array_map 去除数组参数里面左右两端空格
    建立自己的异常类方式
    laravel withCount 统计关联数量
    laravel门面和服务提供者使用
  • 原文地址:https://www.cnblogs.com/For-Miku/p/14420119.html
Copyright © 2011-2022 走看看