Codeforces Beta Round #11, problem: (D) A Simple Task 狀態壓縮DP+記憶化搜素DP

來源:互聯網
上載者:User

題意:在圖中找簡單迴路

/*************看了大神的部落格才有所感悟啊,記憶化搜尋+狀態壓縮。。。。太神了...這種複雜度,近百萬的DFS複雜度居然沒有TLE,果然經驗不足,菜鳥一隻。用狀態壓縮枚舉起點和可能經過的點。可以判定的簡單通路 i->j,存在的條數為sum(i->k) 其中k,j之間有邊。當然,每次計算通路個數的時候,可以借每一個k來判斷迴路的條數,當然只能算一次。這樣加出來的迴路會有重複,因為可能把順逆兩種方向運動的迴路都考慮進去。記憶化搜尋的好處是可以精確的計算每次遍曆點的情況,而如果單純只是迴圈的話,卻沒有這麼靈活。****************/#define LL long long#include<cstdio>#include<cstring>const int LMT=22,LMS=1<<19;LL dp[LMS][LMT],ans;int n,start,tem,gra[LMT][LMT];int get_one(int x){    int res=0;    do    res+=x&1;    while(x>>=1);    return res;}int left(int x){    int d=x&(-x),res=0;    while(d>>=1)res++;    return res;}LL dfs(int mas,int end){    if(dp[mas][end]>=0)return dp[mas][end];    LL res=0;    for(int j=start;j<n;j++)    if(gra[j][end]&&((1<<j)&mas)&&(tem==2||j!=start))    {        tem--;        res+=dfs(mas^(1<<end),j);        tem++;    }    if(tem>2&&gra[end][start])        ans+=res;    dp[mas][end]=res;    return res;}int main(void){    int m,lim;    scanf("%d%d",&n,&m);    memset(dp,-1,sizeof(dp));    while(m--)    {        int u,v;        scanf("%d%d",&u,&v);        u--;v--;        gra[u][v]=gra[v][u]=1;    }    lim=1<<n;    for(int i=0;i<n;i++)dp[1<<i][i]=1;    for(int t=0;t<lim;t++)    {        start=left(t);        tem=get_one(t);        for(int j=start;j<n&&tem>1;j++)        if(gra[j][start]&&((1<<j)&t))           dfs(t,j);    }    printf("%I64d\n",ans>>1);    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.