码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 4011 落忆枫音

时间:2016-11-16 01:33:55      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:str   pac   string   class   blog   std   main   struct   pre   

几个重点:

1.从每个点任选一条入边,都可以成为一个树形图。

2.于是考虑所有答案减去有环的答案。

3.将要求的东西形式化表示出来,然后发现可以直接dp。。

好厉害啊。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxv 100050
#define maxe 200050
#define mod 1000000007
using namespace std;
long long n,m,x,y,a,b,d[maxv],dp[maxv],inv[maxv],ans=1,nume=1,g[maxv],dv[maxv];
queue <long long> q;
struct edge
{
    long long v,nxt;
}e[maxe];
void addedge(long long u,long long v)
{
    e[++nume].v=v;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void get_table()
{
    inv[1]=1;
    for (long long i=2;i<=n;i++) inv[i]=(-(mod/i)*inv[mod%i]%mod+mod)%mod;
}
void topusort()
{
    for (long long i=1;i<=n;i++)
    {
        dv[i]=d[i];
        if (!d[i]) q.push(i);
    }
    while (!q.empty())
    {
        long long head=q.front();q.pop();
        for (long long i=g[head];i;i=e[i].nxt)
        {
            long long v=e[i].v;
            dp[v]+=dp[head]*inv[dv[v]]%mod;if (dp[v]>mod) dp[v]%=mod;
            if (!--d[v]) q.push(v);
        }
    }
}
int main()
{
    scanf("%lld%lld%lld%lld",&n,&m,&x,&y);d[y]++;
    for (long long i=1;i<=m;i++)
    {
        scanf("%lld%lld",&a,&b);
        d[b]++;addedge(a,b);
    }
    for (long long i=2;i<=n;i++) ans=(ans*d[i])%mod;
    if (y==1) {printf("%d\n",ans);return 0;}
    get_table();
    dp[y]=ans*inv[d[y]]%mod;d[y]--;
    topusort();
    printf("%lld\n",(ans-dp[x]+mod)%mod);
    return 0;
}

 

BZOJ 4011 落忆枫音

标签:str   pac   string   class   blog   std   main   struct   pre   

原文地址:http://www.cnblogs.com/ziliuziliu/p/6067684.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!