1. 程式人生 > >hdu 4917 拓撲排序計數

hdu 4917 拓撲排序計數

狀態壓縮dp求解拓撲排序的計數問題。

由於40個點,不能一起求解,不過根據題意,最大的連通塊不超過21,所以分連通塊來求解。

對於拓撲計數的求解可以參見這裡

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
using namespace std;
const long long M=1e9+7;
vector<int>g[44];
vector<int>d[44];
vector<int>pr[44];
long long dp[1<<21];
int p[44],pp[44];
int num;
int res;
long long ans;
int n,m;
long long c[44][44];
bool vis[44];
void pre()
{
    for(int i=0;i<=40;i++)
    {
        for(int j=0;j<=i;j++)
        {
            if(j==0||j==i)c[i][j]=1;
            else
            {
                c[i][j]=c[i-1][j]+c[i-1][j-1];
                c[i][j]%=M;
            }
        }
    }
}
void init()
{
    ans=1;
    res=n;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
    {
        g[i].clear();
        pr[i].clear();
    }
}
void dfs(int u)
{
    vis[u]=1;
    pp[num]=u;
    p[u]=num++;
    int size=g[u].size();
    for(int i=0;i<size;i++)
    {
        int v=g[u][i];
        if(!vis[v])dfs(v);
    }
}
void solve()
{
    for(int i=0;i<num;i++)
    {
        d[i].clear();
        int u=pp[i];
        int size=pr[u].size();
        for(int j=0;j<size;j++)d[i].push_back(p[pr[u][j]]);
    }
    int nn=(1<<num);
    for(int i=0;i<nn;i++)dp[i]=0;
    dp[0]=1;
    for(int i=0;i<nn;i++)
    {
        if(dp[i]==0)continue;
        for(int j=0;j<num;j++)
        {
            if((i&(1<<j))==(1<<j))continue;
            bool ok=0;
            int size=d[j].size();
            for(int k=0;k<size;k++)
            {
                int v=d[j][k];
                if((i&(1<<v))!=(1<<v))
                {
                    ok=1;
                    break;
                }
            }
            if(ok==0)
            {
                dp[i|(1<<j)]+=dp[i];
                dp[i|(1<<j)]%=M;
            }
        }
    }
    ans*=(c[res][num]*dp[nn-1])%M;
    ans%=M;
    res-=num;
}
int main()
{
    int u,v;
    pre();
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
            g[v].push_back(u);
            pr[v].push_back(u);
        }
        for(int i=1;i<=n;i++)
        {
            if(!vis[i])
            {
                num=0;
                dfs(i);
                solve();
            }
        }
        printf("%I64d\n",ans);
    }
    return 0;
}


相關推薦

hdu 4917 排序計數

狀態壓縮dp求解拓撲排序的計數問題。 由於40個點,不能一起求解,不過根據題意,最大的連通塊不超過21,所以分連通塊來求解。 對於拓撲計數的求解可以參見這裡 #include<iostream> #include<cstring> #include

HDU 4857 排序 優先隊列

main std c++ 沒有 back lac 得到 scan bsp n個數,已經有大小關系,現給m個約束,規定a在b之前,剩下的數要盡可能往前移。輸出序列 大小關系顯然使用拓撲結構,關鍵在於n個數本身就有大小關系,那麽考慮反向建圖,優先選擇值最大的入度為零的點,這樣

傳遞 hdu 5961 排序有無環~

name nbsp ems print str using body new eof 題目:http://acm.hdu.edu.cn/showproblem.php?pid=5961 題目為中文,這裏就不描述題意了。 思路: 從題目陳述來看,他將一個有向圖用一個鄰接矩

【題解】洛谷P3953[NOIP2017]逛公園 最短路+排序+計數類DP

題目連結 學習了大佬題解。根據大佬的講解,把對應部分分的程式碼打到一起了。(有點臃腫) #pragma GCC optimize(2) #include<cstdio> #include<cstring> #include<

hdu-2647-排序

Reward Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 13511    Accepte

HDU 2647 排序分層;

Problem Description Dandelion's uncle is a boss of a factory. As the spring festival is coming , he wants to distribute rewards to his workers. Now

HDU 1285--確定比賽名次【排序 &amp;&amp; 鄰接表實現】

eat priority tex eof greate topsort -- str spa 確定比賽名次 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/

排序 HDU - 5695

+= ret include pty pri 包括 log const bin 眾所周知,度度熊喜歡各類體育活動。 今天,它終於當上了夢寐以求的體育課老師。第一次課上,它發現一個有趣的事情。在上課之前,所有同學要排成一列, 假設最開始每個人有一個唯一的ID,從1到NN,在排

HDU 4324:Triangle LOVE( 排序 )

添加 crazy integer single mod world ase ons using pid=4324">Triangle LOVE Time Limit: 2000/1000 MS (Java/Others) Memory

HDU 6073 Matching In Multiplication(排序

str graph pop using bsp sum rod 沒有 script Matching In Multiplication Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/5242

hdu 4324 Triangle LOVE 排序

clu ring ng- Language rip processor ++ ret amp #include<stdio.h> #include<stack> #include<string.h> #include&

hdu 5695 Gym Class (排序)

font gym 輸入 整數 div 情況 -- bit const Description 眾所周知,度度熊喜歡各類體育活動。 今天,它終於當上了夢寐以求的體育課老師。第一次課上,它發現一個有趣的事情。在上課之前,所有同學要排成一列, 假設最開始每個人有一個唯一的ID,從

HDU 1285 確定比賽名次(排序模板)

href 正在 ios dfs als 結束 top 查找 names 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1285 題目大意:有N個比賽隊(1<=N<=500),編號依次為1,2,3,。。。。,N進行

HDU 1285 確定比賽名次(排序基礎題)

個數 排名 有向無環圖 沒有 left php 輸出 編號 整數 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1285 題目: 有N個比賽隊(1<=N<=500),編號依次為1,2,3,。。。。,N進行比賽,

HDU 4857 逃生(排序逆向+鄰接表存圖)

panel scrip topo %d tar ons back int queue 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 題目: Problem Description 糟糕的事情發生啦,現在大家都忙

HDU 4324 Triangle LOVE(排序判環)

rip tdi relation out std program there tour cst 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4324 題目: Problem Description Recently,

HDU 3342 Legal or Not(排序判環)

題解 eas n-1 all day sim contain target there 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3342 題目: Problem Description ACM-DIY is a l

HDU 2647 Reward(排序

empty case acm size col .cn ble ger dem 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2647 題目: Problem Description Dandelion‘s uncle

hdu 2647 Reward(排序+反圖)

nbsp style -- clu empty money sum 心態 基礎 題目鏈接:https://vjudge.net/contest/218427#problem/C 題目大意: 老板要給很多員工發獎金, 但是部分員工有個虛偽心態, 認為自己的獎金必須比某些人

題解報告:hdu 2647 Reward(排序

一個 may lan 應該 遇到 net acm http nes 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2647 Problem Description Dandelion‘s uncle is a boss of