[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. vue安装环境

    vue安装环境 1. 安装node.js 先在电脑上安装node.js, https://nodejs.org/en/ 可以点击链接安装. 安装成功后,在命令板里检测是否安装成功, node -v 2 ...

  2. WPF中矢量图标库

    https://www.iconfont.cn/search/index?searchType=icon&q=人员

  3. Java AES加密算法工具类

    AESCodec.java package util; import java.security.Key; import javax.crypto.Cipher; import javax.crypt ...

  4. ubuntu jdk install

    1.下载jdk-7u75-linux-x64.tar.gz,默认在/home/csf/Downloads 2.csf@ubuntu:~/Downloads$ sudo mkdir /usr/java ...

  5. shell中字符串基本用法

    前言 今天在写脚本时,发现前阶段使用过的一些用法还是需要去百度查找,并且找到的答案还需要自己去筛选,耽误写脚本时间,这一篇对字符串之间的比较和逻辑判断都非常详细,借鉴他人之作,资源共享. 本片主要说明 ...

  6. pytthon + Selenium+chrome linux 部署

    1,centos7 安装 google-chrome (1) 添加chrome的repo源 vi /etc/yum.repos.d/google.repo [google] name=Google-x ...

  7. 二十七、MySQL 复制表

    MySQL 复制表 如果我们需要完全的复制MySQL的数据表,包括表的结构,索引,默认值等. 如果仅仅使用CREATE TABLE ... SELECT 命令,是无法实现的. 本章节将为大家介绍如何完 ...

  8. css清除浮动,清除子节点margin溢出问题

    清除浮动 .clearfix:after{ content:”.”; display:block; height:0; clear:both; visibility:hidden; } 清除margi ...

  9. python3.7 迭代器和生成器

    #!/usr/bin/env python __author__ = "lrtao2010" #python3.7 迭代器和生成器 #迭代器协议: ''' 1.迭代器协议是指:对象 ...

  10. Installing Apps Kattis - installingapps (贪心 + 背包)

    Installing Apps Kattis - installingapps Sandra recently bought her first smart phone. One of her fri ...