zoukankan      html  css  js  c++  java
  • 【题解】 [HNOI2015]落忆枫音 (拓扑排序+dp+容斥原理)


    原题戳我

    Solution:

    (部分复制Navi_Aswon博客

    解释博客中的两个小地方:

    [sum_{left(S是G中y→x的一条路径的点集 ight))}prod_{2≤j≤n,(j∉S)}degree_j ]

    • 因为加了(x)(y)这条边出现了环,所以环上一定有一条边是从(x)连向(y),所以在没有这条边时,能从(y)连向(x)的方案都是不满足的。
    • 因此,上面这个式子就是找出了一条从(y)(x)的路径后,连边的方案数。可以看作,(y)(x)路径上的所有边都固定只连向环中的下一个点,所以方案数就是其他不在环上的点的入度乘积

    [f_i=frac{∑left(j→i ight)*f_j}{degree_i} ]

    • 这个式子(degree)总乘积除掉环路径上的点后的乘积之和,也就是不同环到这个点来后的方案和,所以最后(f[x])就是所有存在环的方案数。注意的理解的点就是,(f[ ])不是一个固定的环存在的不能满足方案数,而是所有环的情况方案数之和

    • 另外还用到了费马小定律求逆元,(1e9+7)是质数

    是一道需要好好理解好好思考的题目


    Code:

    //It is coded by Ning_Mew on 3.17
    #include<bits/stdc++.h>
    #define LL long long
    
    using namespace std;
    
    const int maxn=1e5+7;
    const int MOD=1e9+7;
    
    int n,m,x,y;
    int head[maxn],cnt=0;
    struct Edge{
      int nxt,to;
    }edge[2*maxn];
    int degree[maxn],in[maxn];
    LL ans=0,f[maxn];
    
    void add(int from,int to){
      edge[++cnt].nxt=head[from];
      edge[cnt].to=to;
      head[from]=cnt;
    }
    LL q_pow(int x,int k){
      LL box=1ll*x,ans=1;
      while(k){
        if(k%2)ans=ans*box%MOD;
        box=box*box%MOD;
        k=k/2;
      }return ans;
    }
    void topsort(){
      queue<int>q;
      while(!q.empty())q.pop();
      for(int i=1;i<=n;i++){if(in[i]==0)q.push(i);}
      while(!q.empty()){
        int u=q.front();q.pop();
        f[u]=f[u]*q_pow(degree[u],MOD-2)%MOD;
        for(int i=head[u];i!=0;i=edge[i].nxt){
          int v=edge[i].to;
          in[v]--;f[v]=(f[v]+f[u])%MOD;
          if(in[v]==0)q.push(v);
        }
      }return;
    }
    int main(){
      scanf("%d%d%d%d",&n,&m,&x,&y);
      degree[y]++;
      for(int i=1;i<=m;i++){
        int a,b;scanf("%d%d",&a,&b);
        add(a,b);degree[b]++;
      }
      ans=1;
      for(int i=2;i<=n;i++){
        in[i]=degree[i];
        ans=1ll*ans*degree[i]%MOD;
      }
      in[1]=degree[1];
      in[y]--; f[y]=ans;
      if(y!=1)topsort();
      printf("%lld
    ",(ans-f[x]+MOD)%MOD);
      return 0;
    }
    
    
  • 相关阅读:
    python openpyxl 封装Execl常用操作的方法
    python webdriver grid多节点运行webdriver程序
    url的正则表达式
    基于Erlang VM的函数式编程语言Elixir
    [整理]团队开发效率提升探索一
    FreeBSD应该装gnome3做桌面
    FreeBSD pkg仓库有台湾的镜像了
    再探OAuth2
    【转】Android世界的Swift
    内存只有4G的MBP要怎么破
  • 原文地址:https://www.cnblogs.com/Ning-Mew/p/8588574.html
Copyright © 2011-2022 走看看