[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. jquery循环获取name相同的元素

    今天做项目时,用到一种用jquery循环获取name相同的按钮,并且完成点击事件,记录一下 首先整段的html,是用js拼出来的(项目需求) getStudentArticle:function(op ...

  2. Rhadoop安装

    1.ubuntu,hadoop,R,jdk安装好 2.下载Rhadoop项目的的三个包,rmr,hdfs,rHBase存放到Downloads/R. 3.切换到root 4.安装依赖的库 ~R CMD ...

  3. 关于SQL数据库 msdb.dbo.sp_send_dbmail 函数发送邮件的场景分析

    关于SQL数据库 msdb.dbo.sp_send_dbmail 函数发送邮件的场景分析 在推行系统中,时不时会有用户提出希望系统能自动推送邮件,由于手头的工具和能力有限,不少需求都借助于sql se ...

  4. RuPengGame游戏引擎 精灵 createSprite 创建 setSpritePosition 设置位置 playSpriteAnimate 播放动画 setSpriteFlipX设置翻转 精灵图片下载地址

    package com.swift; import java.awt.Point; import com.rupeng.game.GameCore;//导入游戏引擎包 public class Gam ...

  5. utf8、ansii、unicode编码之间的转换

    #include "stdafx.h"#include "windows.h"#include <iostream>#include <str ...

  6. [未完] term.js 记录遇到的问题

    参考博文:https://www.cnblogs.com/zhenfei-jiang/p/7065038.html 按照网上查找的资料敲了代码 term.on('data', function(dat ...

  7. MYSQL 自定义排序

    在mysql order by排序中,大多数情况下仅使用默认排序规则就够了:字符串按字典顺序,数字按大小等等.可有时候,某个字段是有自身业务含义的,比如 type(1,2,3)可能表示早/中/晚,如果 ...

  8. linux批量替换

    sed -i "s/李三/李四/g"  -r result/*       将result文件夹下的所有文件中的李三替换成李四 sed命令下批量替换文件内容  格式: sed -i ...

  9. Flask学习笔记:数据库迁移操作flask-script+alembic/flask-migrate

    数据库迁移是将代码中模型类(即表)的修改同步到数据库中, flask-sqlalchemy的模型类一旦使用create_all()映射到数据库中后,对这个模型类的修改(例如添加了一个新的字段)就不会再 ...

  10. BFS:HDU3085-Nightmare Ⅱ(双向BFS)

    Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 32768/32768 K (Java/Others) Tot ...