zoukankan      html  css  js  c++  java
  • bzoj 4671: 异或图

    4671: 异或图

    Time Limit: 20 Sec  Memory Limit: 256 MB
    Submit: 61  Solved: 39
    [Submit][Status][Discuss]

    Description

    定义两个结点数相同的图 G1 与图 G2 的异或为一个新的图 G, 其中如果 (u, v) 在 G1 与
    G2 中的出现次数之和为 1, 那么边 (u, v) 在 G 中, 否则这条边不在 G 中.
    现在给定 s 个结点数相同的图 G1...s, 设 S = {G1, G2, . . . , Gs}, 请问 S 有多少个子集的异
    或为一个连通图?

    Input

    第一行为一个整数s, 表图的个数.
    接下来每一个二进制串, 第 i 行的二进制串为 gi, 其中 gi 是原图通过以下伪代码转化得
    到的. 图的结点从 1 开始编号, 下面设结点数为 n.
    Algorithm 1 Print a graph G = (V, E)
    for i = 1 to n do
    for j = i + 1 to n do
    if G contains edge (i, j) then
    print 1
    else
    print 0
    end if
    end for
    end for
     2 ≤ n ≤ 10,1 ≤ s ≤ 60.

    Output

    输出一行一个整数, 表示方案数

    Sample Input

    3
    1
    1
    0

    Sample Output

    4
    这个题还不很明白,对斯特林数还不够了解
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 20
    using namespace std;
    int co[maxn],n,m,s,tot;
    long long fac[maxn],two[70],eq[70],ans;
    bool dis[70][maxn][maxn];
    char h[maxn*maxn];
    void dfs(int x,int m){
        if(x==n+1){
            int top=0;
            for(int i=1;i<=n-1;i++)
                for(int j=i+1;j<=n;j++){
                    if(co[i]!=co[j]){
                        long long t=0;
                        for(int k=1;k<=s;k++)if(dis[k][i][j])t+=two[k-1];
                        for(int k=1;k<=top;k++)if((t^eq[k])<t)t^=eq[k];
                        if(t)eq[++top]=t;
                    }
                }
            ans+=fac[m-1]*two[s-top];
            return;
        }
        for(int i=1;i<=m+1;i++){
            co[x]=i;
            dfs(x+1,m+(i>m));
        }
    }
    int read(){
        char ch=getchar();
        while (ch<'0'||ch>'1') ch=getchar();
        return ch-'0';
    }
    int main(){
        scanf("%d%s",&s,h+1);
        int len=strlen(h+1);
        for(n=1;n<=10;n++)if(n*(n-1)/2==len)break;
        long long t=0;
        for(int i=1;i<=n-1;i++)
        for(int j=i+1;j<=n;j++)
            dis[1][i][j]=h[++t]-'0';
        for(int k=2;k<=s;k++)
        for(int i=1;i<=n-1;i++)
        for(int j=i+1;j<=n;j++)
            dis[k][i][j]=read();
        fac[0]=two[0]=1;
        for(int i=1;i<=n;i++)fac[i]=-1LL*fac[i-1]*i;
        for(int i=1;i<=s;i++)two[i]=two[i-1]*2;
        dfs(1,0);
        cout<<ans<<endl;
    }
  • 相关阅读:
    LeetCode: Number Complement
    LeetCode: Hamming Distance
    LeetCode: Sum of Left Leaves
    LeetCode: Ransom Note
    LeetCode: Minimum Moves to Equal Array Elements
    LeetCode: Linked List Random Node
    LeetCode: Product of Array Except Self
    LeetCode:Two Sum II
    LeetCode: Minimum Moves to Equal Array Elements II
    杂记 -- 时间段内应用程序调用次数限制
  • 原文地址:https://www.cnblogs.com/thmyl/p/8229044.html
Copyright © 2011-2022 走看看