zoukankan      html  css  js  c++  java
  • 【dp】luoguP4796 关于图 想不到是状压dp (┬_┬)

    luoguP4796

    题意:给定一张N个点M条边的无向图,每个点有一个颜色,所有点的颜色共有 K 种,编号为 1…K。求图上有多少条长度至少为 2 的简单路径,满足路径上的每一个点的颜色互不相同。路径上的点的连接顺序不同看作不同的两条路径。

    数据范围:1N,M100000,1K5

    一直朝着搜索的角度去思考,找不到什么明确的方法。

    看了题解。。知道需要状压,但是想不到是状压dp。。。。。。。。。。。。。我dp果然太弱了(;′⌒`)

    做法是:

    设每个点的颜色是c[i],则对i这个点有一个起始状态 (1<<c[i]),所以初始化f[i][1<<c[i]]=1,然后就是,状态转移。

    洛谷题解说得好:

      “ 

        一种先枚举点,再枚举状态进行转移

        一种先枚举状态,再枚举点进行转移

        前者会发现,某一状态的点可能会因为其它点还未被遍历,导致方案数未统计完全

        比如遍历到点i,点i+1可以转移到i点,但点i+1的状态还没处理出来,导致i+1的方案不能统计到i点上

        所以我们使用后者进行状态转移

      ”

    所以 从状态1到状态(1<<k),枚举状态,然后把每个状态转移到连接到的点的状态,这样子必定是 每个状态转移的时候,每个点都考虑到,比枚举点更优。这种思路我很难想到,因为习惯性是枚举点的。

    所以有:

    for(int sta=1;sta<(1<<k);sta++)
        {
            for(int i=1;i<=n;i++)
            {
                if(f[i][sta])
                {
                    if(cal(sta)>1)ans+=f[i][sta];
                    for(int j=0;j<p[i].size();j++)
                    {
                        if(sta&(1<<c[p[i][j]]))continue;
                        f[p[i][j]][sta|(1<<c[p[i][j]])]+=f[i][sta];
                    }
                }
            }
        }
  • 相关阅读:
    jenkins as code 与go语言学习
    VC++ 网络编程总结(一)
    Linux下的C高级编程---学习
    面试前必做4准备
    MFC视图切换大全总结
    多线程编程技术学---学习笔记--线程编程基础知识
    C语言高效编程的几招(绝对实用,绝对经典)
    汇编语言(学习笔记-----[bx]和loop)
    汇编语言(学习笔记----源程序)
    汇编语言(学习笔记----寄存器-内存访问)
  • 原文地址:https://www.cnblogs.com/kkkek/p/11959369.html
Copyright © 2011-2022 走看看