HDOJ-5277 YJC counts stars(DFS)

来源:互联网 发布:python写抢票程序 编辑:程序博客网 时间:2024/05/17 02:02

不难发现,满足条件的点集大小不可能超过4,这样的话进行DFS的深度是很浅的。枚举第一个点,再枚举第二个点,如果第二个点与第一个点有边则继续枚举第三个点,判断是否和前两个点都有边,第四个点同理,并不断更新答案。时间复杂度哦O(n^2),

下面是BC ROUND#46的题解:

首先针对大家提出的m的数据范围的问题,其实对于平面图来说有m3n6……首先五个点的团就是平面图判定中提到的K5,包含子图K5就不是平面图。所以答案只可能是4。那么怎么统计答案呢?暴力枚举第一个点,再枚举第二个点,在枚举第三个,第四个,要求每个点都与前面其他点联通。你会发现这就过了,为什么呢?枚举第一个点是O(n)的,枚举第二个点是O(n2),但是注意m=O(n),于是枚举第三个点只有O(n)次,总次数也是O(n2)的。注意到平面图三元环的个数是O(n)的,因为把一个点的相邻点按照几角排序,那么这些点的连边相当于是若干个区间,而区间不能相交,所以总共就是degi=O(m)degi的。于是枚举第四个点的次数也是O(n)的,总复杂度就是O(n2)。对于n=1000来时完全够了。标算是怎么写的呢,标算采用了特殊的技巧枚举三元环,先枚举边,然后枚举度数较少的点的相邻点,判断是否与另一个点相邻,这样可以证明是O(n1.5)的,至于第四个点,可以16个点压一位,预处理出[0,216)每个数二进制1的个数,就可以统计了,复杂度是O(n1.5+n216),可以快速通过数据。

#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;int n,m,ans,maxm;bool f[1002][1002];int  q[15];void DFS(int p,int sum){    int i,j,k,t;    if(sum==5) return;    if(sum>maxm)    {        maxm=sum;        ans=1;    }    else if(sum==maxm)    {        ans++;    }/*    if(sum==3)    {        for(i=1;i<=3; i++) printf("%d ",q[i]);        printf("\n");    }*/    for(i=p+1;i<=n;i++)    {        k=1;        for(j=1;j<=sum;j++)            if(!f[i][q[j]])            {                k=0;                break;            }        if(k)        {            q[sum+1]=i;            DFS(i,sum+1);        }    }}void work(){    int i,j,k,t,x,y;    memset(f,0,sizeof(f));    memset(q,0,sizeof(q));    maxm=0;    ans=0;    for(i=0;i<n;i++)        scanf("%d%d",&t,&t);    for(i=0;i<m;i++)    {        scanf("%d%d",&x,&y);        f[x][y]=1;        f[y][x]=1;    }    for(i=1;i<=n;i++)    {        q[1]=i;        DFS(i,1);    }    //正在遍历第i个点,集合中已经有1个点了    printf("%d %d\n",maxm,ans);}int main(){    while(scanf("%d%d",&n,&m)!=EOF)        work();    return 0;}


0 0
原创粉丝点击