zoukankan      html  css  js  c++  java
  • 【bzoj4011】落忆枫音

    Portal --> bzoj4011

    Solution

    ​  这题。。看了一眼之后深陷矩阵树定理然后我看了一眼数据范围==

      注意到是有向无环图,DAG有十分多优秀的性质所以,这题需要充分利用这个条件

      首先考虑没有加边的时候,也就是单纯求这个DAG的生成树个数怎么做

    ​  其实仔细想一下不难得出答案就是各个点(除了(1)号点)的入度的乘积

    ​   

      然后我们看加了一条边之后会发生什么

    1、这条边会形成自环:显然答案不变

    2、这条边加入后不会形成环:那直接更新一下入度然后重新再算一遍就好了

    3、这条边加入后会形成一个环:

    ​  重头戏

    ​  正着想其实。。不是特别便于统计,这个时候!正难则反!

    ​  我们考虑从直接按照DAG的方法算出来的答案中减去那些不合法的方案,那么怎么样的方案才是不合法的呢,仔细思考一下,应该就是满足以下两个条件:

    ​  (1)选了((x,y))这条边(就是新连的那条)

    ​  (2)形成了一个环

    ​  然后因为原来的图是DAG,这个环显然应该是包含((x,y))这条边的,或者更加直观地说,这个环应该是((x,y))这条边和一条从(y)(x)的路径组成的

    ​  那么现在问题就转化成了统计从(y)(x)的路径的“方案数”,这里的方案数要打引号是因为。。更准确地说应该是确保选边方案中存在一条(y)(x)路径并且包含((x,y))这条边的生成树个数,具体的统计其实就跟普通的DAG路径计数一样的套路,拓扑排序一波

    ​  我们用(val[x])表示(y)(x)路径的“方案数”,初始化就是(val[y]=)按照DAG方式算出来的答案,然后每一个点转移时候的贡献应该是(val[i]/in[i]),其中(in[i])表示的是在加入((x,y))这条边之后(i)点的入度,具体为什么的话是因为。。走到(i)的时候,(i)的前驱其实已经确定了,所以没有(in[i])种选择

    ​   

    ​  代码大概长这个样子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int N=1e5+10,MOD=1e9+7;
    struct xxx{
    	int y,nxt;
    }a[N*2];
    queue<int> q;
    int h[N],in[N],d[N],val[N];
    int vis[N];
    int n,m,tot,ans,X,Y,ans1;
    void add(int x,int y){a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot;}
    void dfs(int x){
    	int u;
    	vis[x]=true;
    	for (int i=h[x];i!=-1;i=a[i].nxt){
    		u=a[i].y;
    		if (vis[u]) continue;
    		dfs(u);
    	}
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	int x,y;
    	scanf("%d%d",&n,&m);
    	scanf("%d%d",&X,&Y);
    	memset(h,-1,sizeof(h));
    	tot=0;
    	for (int i=1;i<=m;++i){
    		scanf("%d%d",&x,&y);
    		add(x,y);
    		++in[y];
    	}
    	ans=1;
    	for (int i=2;i<=n;++i)
    		ans=1LL*ans*in[i]%MOD;
    	if (X==Y){printf("%d
    ",ans);return 0;}
    	dfs(Y);
    	if (!vis[X]){
    		++in[Y];
    		ans=1;
    		for (int i=2;i<=n;++i) ans=1LL*ans*in[i]%MOD;
    		printf("%d
    ",ans);
    	}
    	else{
    		for (int i=h[Y];i!=-1;i=a[i].nxt)
    			--in[a[i].y];
    		ans1=1;
    		for (int i=2;i<=n;++i) ans1=1LL*ans1*in[i]%MOD;
    		ans=(1LL*ans+ans1)%MOD;
    		printf("%d
    ",ans);
    	}
    }
    
  • 相关阅读:
    (九)MySQL用户和权限管理
    activemq修改admin密码
    zookeeper与activemq整合
    (十一)数组array
    (十)while和until循环
    (八)MySQL索引操作
    查看MySQL是否在运行
    MySQL的启动和关闭
    常用的Web服务器软件整理
    [CodeForce 801A] Vicious Keyboard
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9525695.html
Copyright © 2011-2022 走看看