• 4160: [Neerc2009]Exclusive Access 2


    http://www.lydsy.com/JudgeOnline/problem.php?id=4160

      给一张无向图,求定向后所成DAG的最长路的最小值。

      因为点数比较少,考虑状态压缩DP。

      根据 Dilworth 定理,有向无环图的最长链长度,等于最少反链划分数量。所以问题等价于,把点集分成若干集合,使得每个子集内部没有边。转化后的问题可以用状态压缩动态规划解决,预处理出ok[code]表示集合code内部是否有边,然后计算f[code]表示把集合code划分的最少子集数量,转移的时候枚举subcode满足ok[subcode]为真,用f[code-subcode]+1更新答案。总的时间复杂度是 O(2nm+3n)。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=15,maxc=26;
    bool ok[1<<maxn];
    int n,m,idx[maxc],g[maxn][maxn],f[1<<maxn];
    void init(){
        scanf("%d",&m);
        memset(idx,-1,sizeof(idx));
        for (int i=1;i<=m;++i){
            char s1[2],s2[2];
            scanf("%s%s",s1,s2);
            if (idx[s1[0]-'A']==-1) idx[s1[0]-'A']=n++;
            if (idx[s2[0]-'A']==-1) idx[s2[0]-'A']=n++;
            g[idx[s1[0]-'A']][idx[s2[0]-'A']]=g[idx[s2[0]-'A']][idx[s1[0]-'A']]=1;
        }
    }
    void work(){
        for (int i=0;i<1<<n;++i){
            ok[i]=1;
            for (int j=0;j<n;++j)
                for (int k=0;k<n;++k)
                    if (j!=k&&((i>>j)&1)&&((i>>k)&1)&&g[j][k]){ok[i]=0;break;}
        }
        memset(f,63,sizeof(f));f[0]=0;
        for (int i=0;i<1<<n;++i)
            for (int t=i;t;t=(t-1)&i)
                if (ok[t]) f[i]=min(f[i],f[i^t]+1);
        printf("%d
    ",f[(1<<n)-1]-2);
    }
    int main(){
        init();
        work();
        return 0;
    }
    my code
  • 相关阅读:
    AMD64 Instruction-Level Debugging With dbx
    Solaris 10上安装Oracle 11g
    Dave-oracle
    SSD 下的 MySQL IO 优化
    vmware 网络工作方式
    PLSQL Developer 配置Oralce11g连接 转
    LINUX下的21个特殊符号 转
    linux 内核调试相关资料
    mysql 源代码编绎
    Windows Performance Toolkit
  • 原文地址:https://www.cnblogs.com/iamCYY/p/4831344.html
Copyright © 2020-2023  润新知