【UOJ #279】【UTR #2】题目交流通道
http://uoj.ac/problem/279
先判断答案为0的情况,\(d(i,i)\neq 0\),\(d(i,j)\neq d(j,i)\),\(d(i,j)>d(i,k)+d(k,j)\),\(d(i,j)>k\)。
对于\(d(i,j)>0\)的情况,如果存在\(k\neq i,j\)且满足\(d(i,j)=d(i,k)+d(k,j)\),那么i和j的边就可以取d(i,j)~k的所有权值,答案乘上\(k-d(i,j)+1\)即可。
如果存在\(d(i,j)=0\)的情况,用并查集把最短距离为0的点缩起来,形成许多连通块。两个连通块之前会有很多边,且这些边的d值相同。把连通块看成一个点,那么就成了上一行的问题中有d值相同重边的情况;设ij之间的重边数为a,这个情况中如果存在上一行所述的k,答案乘上\((k-d(i,j)+1)^a\);如果不存在上一行所述的k,答案乘上\((k-d(i,j)+1)^a-(k-d(i,j))^a\)。
对于每个连通块内的方案数,假设连通块大小为n,设边权为0的边连通整个连通块的方案数为\(f(n)\),不管连不连通所有边权任意的方案数为\(g(n)\),因为这个连通块是个完全图,所以\(g(n)=(k+1)^{\frac{n(n-1)}2}\),同时:$$f(n)=g(n)-\sum_{i=1}^{n-1}f(i)g(n-i)
\begin{pmatrix}n-1\i-1\ \end{pmatrix} k^{i(n-i)}$$
先定住一个连通块内的点x,转移时枚举包括x的连通块的大小\(f(i)\)。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 403;
const int p = 998244353;
int fa[N], d[N][N], n, k, F[N], G[N], jc[N], jcn[N], cnt[N][N], sum[N];
inline int ipow(int a, int b) {
int r = 1, w = a;
while (b) {
if (b & 1) r = 1ll * r * w % p;
b >>= 1;
w = 1ll * w * w % p;
}
return r;
}
inline int C(int a, int b) {return 1ll * jc[a] * jcn[b] % p * jcn[a - b] % p;}
inline void sub(int &a, int b) {a -= b; if (a < 0) a += p;}
int find(int x) {return fa[x] == x ? x : fa[x] = find(fa[x]);}
inline void merge(int a, int b) {
if ((a = find(a)) != (b = find(b)))
fa[a] = b;
}
int ans = 1;
int main() {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j) {
scanf("%d", &d[i][j]);
if (d[i][j] > k) {puts("0"); return 0;}
}
for (int i = 1; i <= n; ++i) {
if (d[i][i] != 0) {puts("0"); return 0;}
for (int j = i + 1; j <= n; ++j)
if (d[i][j] != d[j][i])
{puts("0"); return 0;}
}
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
for (int kk = 1; kk <= n; ++kk)
if (d[i][j] > d[i][kk] + d[kk][j])
{puts("0"); return 0;}
jc[0] = jcn[0] = 1;
for (int i = 1; i <= n; ++i) {
jc[i] = 1ll * jc[i - 1] * i % p;
jcn[i] = ipow(jc[i], p - 2);
}
for (int i = 1; i <= n; ++i) {
F[i] = G[i] = ipow(k + 1, i * (i - 1) / 2);
for (int j = 1; j < i; ++j)
sub(F[i], 1ll * F[j] * G[i - j] % p * C(i - 1, j - 1) % p * ipow(k, j * (i - j)) % p);
}
for (int i = 1; i <= n; ++i) fa[i] = i;
for (int i = 1; i <= n; ++i)
for (int j = i + 1; j <= n; ++j)
if (d[i][j] == 0)
merge(i, j);
int u, v;
for (int i = 1; i <= n; ++i)
for (int j = i + 1; j <= n; ++j)
if ((u = find(i)) != (v = find(j)))
++cnt[u][v], ++cnt[v][u];
int a;
for (int i = 1; i <= n; ++i)
for (int j = i + 1; j <= n; ++j)
if (a = cnt[i][j]) {
bool flag = false;
for (int kk = 1; kk <= n; ++kk)
if (cnt[i][kk] && cnt[kk][j] && d[i][j] == d[i][kk] + d[kk][j]) {
flag = true;
break;
}
if (flag) ans = 1ll * ans * ipow(k - d[i][j] + 1, a) % p;
else ans = 1ll * ans * ((ipow(k - d[i][j] + 1, a) - ipow(k - d[i][j], a) + p) % p) % p;
}
for (int i = 1; i <= n; ++i) ++sum[find(i)];
for (int i = 1; i <= n; ++i)
if (sum[i]) ans = 1ll * ans * F[sum[i]] % p;
printf("%d\n", ans);
return 0;
}
【UOJ #279】【UTR #2】题目交流通道的更多相关文章
- 【UTR #2】[UOJ#278]题目排列顺序 [UOJ#279]题目交流通道 [UOJ#280]题目难度提升
[UOJ#278][UTR #2]题目排列顺序 试题描述 “又要出题了.” 宇宙出题中心主任 —— 吉米多出题斯基,坐在办公桌前策划即将到来的 UOI. 这场比赛有 n 道题,吉米多出题斯基需要决定这 ...
- uoj#279. 【UTR #2】题目交流通道(容斥+数数)
传送门 先考虑无解的情况,为以下几种:\(dis_{i,j}+dis_{j,k}<dis_{i,k}\),\(dis_{i,i}\neq 0\),\(dis_{i,j}\neq dis_{j,i ...
- UOJ279 【UTR #2】题目交流通道
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump ...
- 【UTR #2】题目交流通道
题目描述 定好了难度,雄心勃勃的吉米多出题斯基开始寻找智慧的神犇星球的居民出题. 然而吉米多出题斯基没有料到,神犇星球的居民告诉吉米多出题斯基:"今年神犇星球经济不景气,大家都想宅在家里,哪 ...
- uoj279题目交流通道(dp)
题目大意: 神犇星球有 \(n\) 座小城.对于任意两座小城 \(v,u\)\((v≠u)\),吉米多出题斯基想在 \(v,u\) 之间建立一个传送时间为 \(w(v,u)\)的无向传送通道,其中 \ ...
- uoj279 题目交流通道
题目:告诉你每两个点之间的最短路距离.构造每条边边权<=m的无向完全图.求有多少种不同边权的图满足最短路限制?n<=400. 标程: #include<cstdio> #inc ...
- 【uoj#280】[UTR #2]题目难度提升 对顶堆+STL-set
题目描述 给出 $n$ 个数 $a_1,a_2,...,a_n$ ,将其排为序列 $\{p_i\}$ ,满足 $\{前\ i\ 个数的中位数\}$ 单调不降.求字典序最大的 $\{p_i\}$ . 其 ...
- UOJ Test Round #2
昨天晚上打的这个比赛,简直一颗赛艇啊-- 感觉发挥的并不好.比赛的时候比较紧张,最后一题还脑残写了个离散化结果爆零了,哎我怎么这么逗逼-- 讲讲比赛经过吧. 比赛之前逗逼地以为是8:00开始,然后淡定 ...
- 「总结」$dp1$
大概就是做点题. 先列一下要做的题目列表,从\(UOJ\)上找的. 129寿司晚宴 348州区划分 370滑稽树上滑稽果 457数树 22外星人 37主旋律 300吉夫特 196线段树 311积劳成疾 ...
随机推荐
- 【BZOJ】3626 [LNOI2014]LCA
[算法]树链剖分+线段树(区间加值,区间求和) [题解]http://hzwer.com/3891.html 中间不要取模不然相减会出错. 血的教训:线段树修改时标记下传+上传,查询时下传.如果修改时 ...
- 【51NOD】1096 距离之和最小
[算法]数学 [题解] 其实就是求中位数,奇数个点就是最中间的点,偶数个点就是最中间两个点和它们之间的区域皆可(所以偶数不必取到两点正中央,取两点任意一点即可). 我们可以想象现在x轴上有n个点,我们 ...
- 【Matlab】绘制饼状统计图
a=tabulate(b); % b为需要绘制饼图的原始数据列,生成新的一个矩阵a label={'1','2','3'} % 设定饼图每块扇形代表的内容 percent=num2str(a(:,3) ...
- Ubuntu 14.04开启ssh服务
sudo apt-get install openssh-server sudo apt-get install openssh-client sudo service ssh restart
- Linux NAPI/非NAPI
本文主要介绍二层收包流程,包括NAPI与非NAPI方式: NAPI:数据包到来,第一个数据包产生硬件中断,中断处理程序将设备的napi_struct结构挂在当前cpu的待收包设备链表softnet_d ...
- MYSQL中INET_ATON()函数
例如我们现在要在一个表中查出 ip 在 192.168.1.3 到 192.168.1.20 之间的 ip 地址,我们首先想到的就是通过字符串的比较来获取查找结果,但是如果我们通过这种方式来查找,结果 ...
- dotnet core多平台开发体验(mac os x 、windows、linux)
前言 随着net core rc2的发布,园子里面关于net core的入门文章也也多了起来,但是大多数都是在一个平台上面来写几个简单的例子,或者是在解释代码本身,并没有体现说在一个平台上面创建一个项 ...
- hive-group by的时候把两个字段变成map
源表结构: pcgid string mobilegid string value double 测试数据如下: p1 m1 ...
- Valid Number——分情况讨论最经典的题(没细看)——这题必须静下心来好好看看
Validate if a given string is numeric. Some examples: "0" => true " 0.1 " =&g ...
- react初体验
function Guest() { return ( <h1>pls login in</h1> ); } function User() { return ( <h1 ...