bzoj 1016 深搜

  首先我们知道MST的一些性质,对于这道题来说就是,假设我们先求出一颗MST设为G,由已知边权相同的边最多会有10条,那么假设我们在这10条边中选取size条边∈G,那么我们在这边权相同的边集E中任意选取size条有意义的边,这里的有意义的边的定义为每条边都会造成新的连通性的增加,那么边集E中所有的size条有意义的边的方案我们可以通过dfs求出,然后我们将不同边权的边的方案求连乘,就是MST的方案数。

  ps:我们没有必要求一遍MST,我们可以一边做kruskal,一边维护图的连通性,然后每找到一个权值不同的边集E时深搜。

  反思:做dfs的时候使用并查集维护图的连通性,但是加了路径压缩,这样就会在找块的祖先的时候改变不同节点的父亲,这样就没有办法在dfs时恢复原图,所以我们应该只用并查集维护节点的父亲而不是祖先,找了半天才找到这里的错误。

  

/**************************************************************

    Problem: 1016

    User: BLADEVIL

    Language: C++

    Result: Accepted

    Time:8 ms

    Memory:820 kb

****************************************************************/

 

//By BLADEVIL

#include <cstdio>

#include <cstring>

#include <algorithm>

#define maxn 110

#define maxm 1010

#define d39 31011

 

using namespace std;

 

int n,m;

int father[maxn],curfather[maxn];

struct rec

{

    int a,b,len;

} c[maxm];

 

bool cmp(rec a,rec b)

{return (a.len<b.len);}

 

int getfather(int x)

{

    if (father[x]==x) return x;

    return father[x]=getfather(father[x]);

}

 

int getcurfather(int x)

{

    if (curfather[x]==x) return x;

    return getcurfather(curfather[x]);

}

 

int dfs(int l,int r,int size)

{

    //printf("%d %d %d\n",l,r,size);

    if (!size) return 1;

    if (l>r) return 0;

    int fa,fb,cur=0;

    cur=dfs(l+1,r,size);

    fa=getcurfather(c[l].a); fb=getcurfather(c[l].b);

    if (fa!=fb)

    {

        curfather[fa]=fb;

        cur+=dfs(l+1,r,size-1);

        curfather[fa]=fa;

    }

    return cur;

}

 

int main()

{

    int ans=1,cnt=0;

    scanf("%d%d",&n,&m);

    for (int i=1;i<=m;i++) scanf("%d%d%d",&c[i].a,&c[i].b,&c[i].len);

    sort(c+1,c+m+1,cmp);

    for (int i=1;i<=n;i++) father[i]=curfather[i]=i;

    int cur=0;

    int l,r,size=0;

    for (int i=1;i<=m+1;i++)

    {

        if (cur!=c[i].len)

        {

            r=i-1;

            //if (i!=1) printf(" %d %d %d\n",l,r,size);

            if (i!=1) ans=(ans*=dfs(l,r,size))%d39;

            l=i;

            size=0;

            cur=c[i].len;

            memcpy(curfather,father,sizeof curfather);

        }

        int fa,fb;

        fa=getfather(c[i].a); fb=getfather(c[i].b);

        if (fa!=fb)

        {

            size++;

            cnt++;

            father[fa]=fb;

        }

    }

    if (cnt!=n-1) printf("0\n"); else printf("%d\n",ans);

    return 0;

}

 

你可能感兴趣的:(ZOJ)