CodeForces 11D A Simple Task

题目:http://codeforces.com/problemset/problem/11/D

题意:给定一个图,求图中环的数目

为了消除重复计算,我们要从每个点出发,并将这个点作为环的最小点,再次回到出发点时就变成了环

但是这样依然有重复,会有1条边重复走2次的环,同时还会将大于3的环正向跑一遍逆向跑一遍

所以最后答案需要-m再除2

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
int a[25][25];
long long dp[1<<19][19];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    memset(a,0,sizeof(a));
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        x--;y--;
        a[x][y]=a[y][x]=1;
    }
    memset(dp,0,sizeof(dp));
    for(int i=0;i<n;i++)
        dp[1<<i][i]=1;
    int tot=1<<n;
    long long ans=0;
    for(int st=0;st<tot;st++)
    {
        for(int i=0;i<n;i++)
        {
            if (dp[st][i]==0) continue;
            for(int j=0;j<n;j++)
                if (a[i][j])
            {
                if ((st&-st)>1<<j) continue;
                if (st>>j&1)
                {
                    if ((st&-st)==1<<j)
                        ans+=dp[st][i];
                }
                else dp[st|1<<j][j]+=dp[st][i];
            }
        }
    }
    ans=(ans-m)>>1;
    printf("%lld\n",ans);
    return 0;
}

  

时间: 2024-10-09 04:07:11

CodeForces 11D A Simple Task的相关文章

[CodeForces 11D] A Simple Task - 状态压缩入门

状态压缩/Bitmask 在动态规划问题中,我们会遇到需要记录一个节点是否被占用/是否到达过的情况.而对于一个节点数有多个甚至十几个的问题,开一个巨型的[0/1]数组显然不现实.于是就引入了状态压缩,用一个整数的不同二进制位来表示该节点的状态. Description Given a simple graph, output the number of simple cycles in it. A simple cycle is a cycle with no repeated vertices

Codeforces 11D - A Simple Task (状压DP)

题意 求出一个n个点m个边的图,求简单环有多少(没有重复点和边). 思路 这是个不错的题,这个状压dp保存的状态不是直接的环,而是路径的个数.s表示的状态为一条路径,则dp[s][i]表示以s的最小编号为起点,以i为终点的环的个数.那么我们就可以通过枚举状态,枚举状态中的起点和枚举路径外的终点,然后判断终点和起点是否相连来判断是否成环. 代码 #include <stdio.h> #include <string.h> #include <iostream> #incl

计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task

E. A Simple Task Problem's Link: http://codeforces.com/problemset/problem/558/E Mean: 给定一个字符串,有q次操作,每次操作将(l,r)内的字符升序或降序排列,输出q次操作后的字符串. analyse: 基本思想是计数排序. 所谓计数排序,是对一个元素分布较集中的数字集群进行排序的算法,时间复杂度为O(n),但使用条件很苛刻.首先对n个数扫一遍,映射出每个数字出现的次数,然后再O(n)扫一遍处理出:对于数字ai,

Codeforces 558E A Simple Task (计数排序&amp;&amp;线段树优化)

题目链接:http://codeforces.com/contest/558/problem/E E. A Simple Task time limit per test5 seconds memory limit per test512 megabytes inputstandard input outputstandard output This task is very simple. Given a string S of length n and q queries each quer

Codeforces 558E A Simple Task

Discription This task is very simple. Given a string S of length n and q queries each query is on the format i j k which means sort the substring consisting of the characters from i to j in non-decreasing order if k?=?1 or in non-increasing order if 

cf 11D A Simple Task(数压DP)

题意: N个点构成的无向图,M条边描述这个无向图. 问这个无向图中共有多少个环. (1 ≤ n ≤ 19, 0 ≤ m) 思路: 例子: 4 6 1 2 1 3 1 4 2 3 2 4 3 4 答案:7 画个图发现,直接暴力DFS有太多的重复计算.用DP. 枚举点数(状态),每个状态的起点.终点(起点可以不用枚举,因为反正是一个环,谁作为起点都一样). dp[S][i]:状态是S,i是终点   含义:从S中的第一个数s出发到达第i个点的方案数.如果s和i相加,总方案数ans+=dp[S][i]

codeforces 558E A Simple Task 线段树

题目链接 题意较为简单. 思路: 由于仅仅有26个字母,所以用26棵线段树维护就好了,比較easy. #include <iostream> #include <string> #include <vector> #include <cstring> #include <cstdio> #include <map> #include <queue> #include <algorithm> #include &

[线段树] codeforces 558E. A Simple Task

题意: 给一个长度n的字符串,q次操作,每次操作把[l,r]排序,k=0非递增,k=1非递减. 题解: 采用计数排序的复杂度是O(n?q),无法通过,但有所启示. 可以看出计数就是区间求和,排序就是区间更新,可以用线段树维护. 做法是建立26棵线段树,第i棵树维护第i个字母的位置信息. 计数时,在26棵线段树内分别做一次查询,排序时根据递增还是递减,把相应的区间赋值为相应的字母. #include<bits/stdc++.h> #define lson rt<<1,l,mid #d

CF 11D A Simple Task 题解

题面 这道题的数据范围一看就是dfs或状压啦~ 本文以状压的方式来讲解 f[i][j]表示目前的节点是i,已经经历过的节点的状态为j的简单环的个数: 具体的转移方程和细节请看代码: PS:(i&-i)的意义便是树状数组 #include <bits/stdc++.h> using namespace std; int n,m; int a[20][20]; long long f[20][1000010]; long long ans; int main () { cin>>