[TC_SRM_460]TheCitiesAndRoadsDivOne

试题描述

John and Brus have become very famous people all over the world, especially in Bolivia. Once they decided to visit their fan club in Bolivia. John has an old map of Bolivia which shows all of its cities and the roads connecting them. All roads are bidirectional, meaning they can be traversed in both directions. Since the map is old, it's possible that some additional roads have been built since the map was produced. However, roads are never destroyed in Bolivia, so all the roads on the map still exist.

Brus has discovered on the Internet that each pair of Bolivian cities now has at least one and at most two simple paths connecting them. A path between cities \(A\) and \(B\) is a sequence of cities starting with \(A\) and ending with \(B\) such that there's a road between each pair of consecutive cities in the sequence. The path is considered simple if it consists of distinct cities.

John and Brus have decided to add some new roads to the old map in such a way that the resulting map satisfies this condition. They can only add a road between a pair of cities if that road did not already exist in the old map. They can't add more than one road between the same pair of cities, and they can't add a road that leads from a city to itself. All added roads must be bidirectional.

You are given a map. The \(j\)-th character of the \(i\)-th element of map will be Y if there is a road between the \(i\)-th and \(j\)-th cities on the old map, or N otherwise. Return the number of ways John and Brus can add new roads to the old map modulo \(1234567891\). Two ways are considered different if the sets of added roads are distinct. The order in which roads are added does not matter.

给一个 \(n\)(\(\le 20\))个节点的无向图,求加一些边使得图成为一棵树或者一棵单环树的方案数(答案对 \(1234567891\) 取模)。

输入

传给你一个 string[] 类型的参数

输出

返回一个整数表示答案

输入示例1

{"NNNNNNNNNNNN", "NNNNNNNNNNNN", "NNNNNNNNNNNN", "NNNNNNNNNNNN", "NNNNNNNNNNNN", "NNNNNNNNNNNN", "NNNNNNNNNNNN", "NNNNNNNNNNNN", "NNNNNNNNNNNN", "NNNNNNNNNNNN", "NNNNNNNNNNNN", "NNNNNNNNNNNN"}

输出示例1

Returns: 1137797187

输入示例2

{"NYYNN", "YNYNN", "YYNNN", "NNNNY", "NNNYN"}

输出示例2

Returns: 6

数据规模及约定

见“试题描述

题解

如果只需要组成树而不是单环树,那么就是明明的烦恼这题,prufer 序列即可,注意每个连通块缩成一个点后需要加权,因为它们大小不一。

这道题我们受它启发,当有一个环的时候,我们枚举哪些连通块组成了一个环,然后组成环的方案乘上接下来组成树的方案(仍可用 prufer 序列计算)就可以了。

注意这题有很多情况需分类讨论(以下只强调特殊情况):

  • 图中已经包含了一个环(这类情况中还需注意所有点都连成了同一个连通分量的情况);

  • 连成环的连通分量只有 \(1\) 个(如果这个连通分量大小小于 \(3\) 则不能用这个连通分量创造环);

  • 连城环的连通分量只有 \(2\) 个(需要考虑重边问题)。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
#define rep(i, s, t) for(int i = (s); i <= (t); i++)
#define dwn(i, s, t) for(int i = (s); i >= (t); i--) int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 25
#define maxs 1048576
#define MOD 1234567891
#define LL long long class TheCitiesAndRoadsDivOne {
private:
char str[maxn];
int n, fa[maxn], siz[maxn], Siz[maxn], cntb;
bool hasc[maxn];
int findset(int x) { return x == fa[x] ? x : fa[x] = findset(fa[x]); } LL Pow(int a, int b) {
LL ans = 1, t = a;
while(b) {
if(b & 1) (ans *= t) %= MOD;
(t *= t) %= MOD; b >>= 1;
}
return ans;
} int cbit[maxs], Log[maxs], fac[maxn]; public:
int find(vector <string> field) {
n = field.size();
fac[0] = 1;
rep(i, 1, n) fa[i] = i, siz[i] = 1, fac[i] = (LL)fac[i-1] * i % MOD;
rep(i, 1, n) {
strcpy(str + 1, field[i-1].c_str());
rep(j, 1, n) if(i < j && str[j] == 'Y') {
int u = findset(i), v = findset(j);
if(u == v) hasc[u] = 1;
else fa[v] = u, siz[u] += siz[v];
}
} bool cyc = 0;
rep(i, 1, n) if(findset(i) == i) Siz[cntb++] = siz[i], cyc |= hasc[i];
LL ans;
if(cntb == 1) ans = 1;
else {
ans = Pow(n, cntb - 2);
rep(i, 0, cntb - 1) (ans *= Siz[i]) %= MOD;
}
if(cyc) return ans; int all = (1 << cntb) - 1;
rep(s, 1, all) cbit[s] = cbit[s&~(s&-s)] + 1, Log[s] = s == 1 ? 0 : Log[s>>1] + 1;
rep(s, 1, all) {
LL tmp;
int csiz = 0, tot;
if(cbit[s] == 1) {
csiz = Siz[Log[s]];
if(csiz < 3) continue;
tmp = (((LL)csiz * (csiz - 1) >> 1) % MOD + MOD - csiz + 1) % MOD;
}
else if(cbit[s] == 2) {
int t1 = s & -s, t2 = (s ^ t1) & -(s ^ t1);
t1 = Log[t1]; t2 = Log[t2];
if(Siz[t1] == 1 && Siz[t2] == 1) continue;
csiz = Siz[t1] + Siz[t2];
tmp = (LL)Siz[t1] * Siz[t2] % MOD;
tmp = (tmp * (tmp - 1) >> 1) % MOD;
}
else {
tmp = 617283946ll * fac[cbit[s]-1] % MOD;
rep(i, 0, cntb - 1) if(s >> i & 1)
csiz += Siz[i], (tmp *= (LL)Siz[i] * Siz[i] % MOD) %= MOD;
}
tot = cntb - cbit[s] + 1;
if(tot > 1) {
(tmp *= Pow(n, tot - 2) % MOD * csiz % MOD) %= MOD;
rep(i, 0, cntb - 1) if(!(s >> i & 1)) (tmp *= Siz[i]) %= MOD;
}
(ans += tmp) %= MOD;
} return ans;
}
};

[TC_SRM_460]TheCitiesAndRoadsDivOne的更多相关文章

  1. topcoder srm 460 div1

    problem1 link 设$f[i][j]$表示已经分配了answers中的前$i$个,分配给的问题的状态为 $j$的方案数. 其中状态可以用$n$位的三进制表示,0表示还未分配,1表示已分配是 ...

随机推荐

  1. web跨域及cookie相关知识总结

    原文:web跨域及cookie相关知识总结   之前对于跨域相关的知识一致都很零碎,正好现在的代码中用到了跨域相关的,现在来对这些知识做一个汇总整理,方便自己查看,说不定也可能对你有所帮助. 本篇主要 ...

  2. 深入理解Java GC

    一.概述 GC(Carbage Collection)垃圾收集器,由JVM自动回收已死亡的对象垃圾. 这也是Java与C++等语言的主要区别之一. 二.如何确认对象已死 1. 引用计数算法 引用计数法 ...

  3. D-bus交叉编译

    在嵌入式中如果需要Qt系统支持U盘插拔,则需要Qt支持D-bus. D-bus的交叉编译依赖expat库,此库为XML解析库. 交叉编译expat库: #./configure --host=XXX ...

  4. 1045: [HAOI2008] 糖果传递

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4897  Solved: 2457[Submit][Status][Discuss] Descript ...

  5. hibernate系列之二

    首先先介绍一下持久化: 持久化:将程序数据在持久状态和瞬时状态间转换的机制:即将内存的数据永久存在关系型数据库中: 持久化类的编写规则: 持久化类需要提供无参构造方法: 持久化类的属性需要私有,对私有 ...

  6. 初学puppet

    初学puppet puppet是什么? puppet是一个开源的软件自动化配置和部署工具,很多大型IT公司均在使用puppet对集群中的软件进行管理和部署. Puppet简介 Puppet的目录是让管 ...

  7. php - 去除php代码中的多余空格

    <?php class Test{ public function test(){ $tmplContent = file_get_contents('./test.php'); $tmplCo ...

  8. thinkphp 3.2.3 程序执行时序图

  9. Elizabeth Taylor【伊丽莎白·泰勒】

    Elizabeth Taylor People fell in love with Elizabeth Taylor in 1944, when she acted in the movie Nati ...

  10. LightOJ - 1341 Aladdin and the Flying Carpet(数论)

    题意 有一块矩形(也可能是正方形)的飞毯. 给定飞毯的面积\(n\)和最小可能的边长\(a\),求可能有多少种不同边长的飞毯.(\(1<=a<=n<=1e12\)) 如面积\(n=6 ...