tc-srm704-div1-1000 解題報告__構造

來源:互聯網
上載者:User

題意:構造一個點數不超過20無重邊無自環的有向圖,節點編號從0到n-1,使得從0到n-1的哈密頓路徑數量恰好為k。

感覺完全沒有思路。。不知道怎麼構造。
去看了下別人的代碼,原來可以做成1<-2<-…<-18一條路徑,然後1-18都向編號比它大的節點連邊。這樣的話往回走就只有唯一的路徑,所以假如說我當前在i,走到了j,j>i,那麼就需要立刻從j到j-1直到i+1,然後再往後走。這樣就相當於每個節點有選或不選兩種狀態,如果選的話就是從前面第一個比它小的選的節點跳過來,不選的話就是從i+1過來。所以如果有0->i,就相當於貢獻了 218−i−1(1≤i<18) 2^{18-i-1}(1\le i(因為18是必選的,19不能回到18)。

既然不會做的話,那就亂搞一下吧~
假如說隨便確定了一個圖,怎麼求路徑數量呢。那就需要 O(220202) O(2^{20}20^2)的狀壓dp。不過我們可以先不求0->n-1的哈密頓路徑數量,可以先求 i−>19,1≤i<19 i->19,1\le i,然後再連從0出去的邊,這樣的話就相當於是問是否存在一個子集和恰好為k。
我們知道 (189) \binom{18}{9}是一個非常大的數了,所以如果i->19的路徑數量是在 k9 k\over 9附近隨機,那麼就很容易一不小心就湊出個k來。所以我們可以二分邊的總數,直到找到一個邊的總數在那裡隨機 i−>19 i->19的路徑數量的平均值會離 k9 k\over 9比較近,然後就在那裡一直隨機。
這樣的話時間複雜度是 O(2nn2logn)≈109 O(2^nn^2\log n)≈10^9的。所以dp的常數比較要用心卡一下才行。。。我一開始算錯了時間複雜度以為是 O(2nnlogn) O(2^nn\log n)的就沒管,結果範例都過不去。。。

代碼:

#include<bits/stdc++.h>using namespace std;const int n=20,N=20;typedef long long LL;class HamiltonianConstruction{    public:        pair<int,int> edge[N*N];        int etot;        LL f[1<<N][N];        LL s[1<<N];        int prev[N];        int bit[1<<N];        inline void cal(int mid)        {            random_shuffle(edge,edge+etot);            memset(prev,0,sizeof(prev));            for(int i=mid;i--;)prev[edge[i].second-1]|=1<<edge[i].first-1;            memset(f,0,sizeof(f));            f[1<<n-2][n-2]=1;            for(int i=1;i<1<<n-1;++i)                for(int j=i,x;j;j^=1<<x)                    if(f[i][x=bit[j&-j]])                        for(int k=prev[x]&~i,y;k;k^=y)                        {                            y=k&-k;                            f[i|y][bit[y]]+=f[i][x];                        }            for(int i=n-2;i--;)s[1<<i]=f[(1<<n-1)-1][i];            for(int i=1;i<1<<n-2;++i)s[i]=s[i^i&-i]+s[i&-i];        }        inline vector<string> construct(int k)        {            for(int i=0;i<n;++i)bit[1<<i]=i;            for(int i=n-1;--i;)                for(int j=n;--j;)                    if(i!=j)                        edge[etot++]=make_pair(i,j);            vector<string> ans(N,string(N,'N'));            int l=0,r=100;            while(r-l>1)            {                int mid=l+r>>1;                cal(mid);                for(int i=1<<n-2;i--;)                    if(s[i]==k)                    {                        for(int j=mid;j--;)ans[edge[j].first][edge[j].second]='Y';                        for(int j=n-2;j--;)                            if(i>>j&1)                                ans[0][j+1]='Y';                        return ans;                    }                LL sum=0;                for(int i=n-2;i--;)sum+=s[1<<i];                if(sum>=k<<1)r=mid;                else l=mid;            }            for(;;)            {                cal(r);                for(int i=1<<n-2;i--;)                    if(s[i]==k)                    {                        for(int j=r;j--;)ans[edge[j].first][edge[j].second]='Y';                        for(int j=n-2;j--;)                            if(i>>j&1)                                ans[0][j+1]='Y';                        return ans;                    }            }        }};

總結:
①構造的時候可以考慮一些特殊情況,或者根據題目中的特殊性質。比如說構造一個圖,就可以先考慮一條鏈、完全圖、樹。
②如果沒有構造的思路,不妨試試隨機化。
③一定要算好時間複雜度。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.