题目描述

定好了难度,雄心勃勃的吉米多出题斯基开始寻找智慧的神犇星球的居民出题。

然而吉米多出题斯基没有料到,神犇星球的居民告诉吉米多出题斯基:“今年神犇星球经济不景气,大家都想宅在家里,哪有心思出来出题呢?”

为了挽救这一局面,吉米多出题斯基决定为神犇星球建一些高速传送通道促进该星球各地区之间交流题目。

神犇星球有 $n$ 座小城。对于任意两座小城 $v, u$($v \neq u$),吉米多出题斯基想在 $v, u$ 之间建立一个传送时间为 $w(v, u)$ 的无向传送通道,其中 $w(v, u)$ 为不超过 $k$ 的非负整数。建成后,神犇星球的居民可从一座小城出发经过一个或若干个传送通道到达另一座小城交流题目,花费的时间为所有经过的传送通道的传送时间之和。

吉米多出题斯基还没有决定每一个传送通道的传送时间取值,只是对于任意两座小城 $v, u$,决定了从 $v$ 出发到达 $u$ 的最短时间要恰好等于 $d(v, u)$。但吉米多出题斯基日理万机,于是他找到了你 —— 风璃殇做不出题耶维奇,请你帮助吉米多出题斯基数一数有多少种不同的满足条件的传送通道建设方案吧!

由于方案数可能很大,你只用输出方案数对 $998244353$($7 \times 17 \times 2^{23}+1$,一个质数)取模后的结果。

输入

第一行两个整数 $n, k$。保证 $n \ge 1, k \ge 0$。

接下来 $n$ 行,每行有 $n$ 个非负整数,第 $i$ 行的 第 $j$ 个数表示 $d(i,j)$ 的值。

输出

输出一行,一个整数,表示方案数对 $998244353$ 取模的结果。如果无解,则方案数为 $0$。

限制与约定

对于所有数据,有 $1\leq n\leq 400, 0\leq k\leq 10^9, 0\leq d(u,v)\leq 10^{9}$

子任务 分值 $n$ $k$ 其他限制
1 30 $1 \leq n \leq 4$ $0\leq k\leq 5$
2 30 $1 \leq n \leq 400$ $0\leq k\leq 10^9$ 对于所有 $u\neq v$,有 $d(u,v)\geq 1$
3 40 $1 \leq n \leq 400$ $0 \leq k \leq 10^9$

分析1

对于第一个子任务,当最大\(n=4\)的时候有\(6\)条边,暴力设定每条边的边权,然后Floyd跑一遍验证一下即可

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#define LL long long using namespace std; inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
} inline void read(int &x){
char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
} int wt,ss[19];
inline void print(int x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {
for (wt=0;x;ss[++wt]=x%10,x/=10);
for (;wt;putchar(ss[wt]+48),wt--);}
} int n,m,ans,a[410][410],b[410][410],c[10]; bool check()
{
for (int k=1;k<=n;k++)
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (i!=j && i!=k && j!=k)
if (b[i][k]+b[k][j]<b[i][j]) b[i][j]=b[i][k]+b[k][j];
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (b[i][j]!=a[i][j]) return false;
return true;
} void dfs(int x)
{
if (x==n*(n-1)/2+1)
{
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (i==j) b[i][j]=0;else b[i][j]=-1;
int s=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (b[i][j]==-1) b[i][j]=c[++s],b[j][i]=c[s];
if (check()) ans++;
return ;
}
for (int i=0;i<=m;i++)
c[x]=i,dfs(x+1);
} int main()
{
read(n);read(m);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
read(a[i][j]);
ans=0;
dfs(1);
print(ans);puts("");
return 0;
}

分析2

对于第二个子任务,数据的特点是\(d(x,y)\geq 1(x\neq y)\)

那么对于一条边\((x,y)\),他的\(d(x,y)\)有两种方式得到,一种是其本身就是最短边,或者是通过两条最短边合成的,即\(d(x,y)=d(x,k)+d(k,y)(x\neq z且y\neq z)\)

那么,对于每一个\((x,y)\),探索是否存在这样一个\(z\),若存在,这条边的边权范围是\([d(x,y),k]\),否则就是能是\(d(x,y)\)了

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#define LL long long using namespace std; inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
} inline void read(int &x){
char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
int wt,ss[19];
inline void print(LL x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
} int n,m,a[410][410];
LL f[410][410];
const LL mo=998244353; bool check(int x,int y)
{
for (int i=1;i<=n;i++)
if (i!=x && i!=y)
if (a[x][i]+a[i][y]==a[x][y]) return true;
return false;
} int main()
{
read(n);read(m);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
read(a[i][j]);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
if (check(i,j)) f[i][j]=(LL)(m-a[i][j]+1);
else f[i][j]=1LL;
}
LL ans=1;
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
ans=ans*f[i][j]%mo;
print(ans),puts("");
return 0;
}

分析3

结合分析1和分析2可以得到60分...还不错了啊......

满分算法的分析...我就把劼的题解搬过来吧......

考虑边可以等于 $0$ 的情况,这时 $d_{u,v}=0$ 的边肯定在图中连成了若干个团。我们把每一个团给缩起来。

两个团之间的点对距离一定是相等的,考虑团与团之间的边,此时相当于有重边的 $d_{u,v}>0$ 的情况。假设这是一条 $a$ 重边,如果存在 $k$ 有 $d_{u,v}=d_{u,k}+d_{k,v}$,那么所有边只要大于等于 $d_{u,v}$ 就可以了,即有 $(K-d_{u,v}+1)^a$ 种方案。如果不存在,那么至少要有一条边等于 $d_{u,v}$,其他边都要大于它,即有 $(K-d_{u,v}+1)^a-(K-d_{u,v})^a$ 种方案。

考虑团内部的边,每个团肯定由 $0$ 的边连成了一个联通块,这是一个经典的容斥,令 $f_i$ 为 $n$ 个点的距离为 $0$ 的团的方案数,$g_i$ 为 $n$ 个点的图的方案数。则有 $g_n=(K+1)^{\binom{n}{2}}$,$f_n=g_n-\sum_{i=1}^{n-1} f_i \times g_{n-i} \times \binom{n-1}{i-1} \times K^{i(n-i)}$。

把所有部分的答案乘起来就好了。时间复杂度 $O(n^3)$,期望得分 $100$ 分。

当然最重要的是要判对无解的情况,大致有四种,分别是 $d_{i,j} >K$,$d_{i,i} \neq 0$,$d_{i,j} \neq d_{j,i}$,$d_{i,j} > d_{i,k}+d_{k,j}$,大力 check 一下就可以了。

【UTR #2】题目交流通道的更多相关文章

  1. 【UTR #2】[UOJ#278]题目排列顺序 [UOJ#279]题目交流通道 [UOJ#280]题目难度提升

    [UOJ#278][UTR #2]题目排列顺序 试题描述 “又要出题了.” 宇宙出题中心主任 —— 吉米多出题斯基,坐在办公桌前策划即将到来的 UOI. 这场比赛有 n 道题,吉米多出题斯基需要决定这 ...

  2. UOJ279 【UTR #2】题目交流通道

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000  作者博客:http://www.cnblogs.com/ljh2000-jump ...

  3. 【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 ...

  4. 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 ...

  5. uoj279题目交流通道(dp)

    题目大意: 神犇星球有 \(n\) 座小城.对于任意两座小城 \(v,u\)\((v≠u)\),吉米多出题斯基想在 \(v,u\) 之间建立一个传送时间为 \(w(v,u)\)的无向传送通道,其中 \ ...

  6. uoj279 题目交流通道

    题目:告诉你每两个点之间的最短路距离.构造每条边边权<=m的无向完全图.求有多少种不同边权的图满足最短路限制?n<=400. 标程: #include<cstdio> #inc ...

  7. 【uoj#280】[UTR #2]题目难度提升 对顶堆+STL-set

    题目描述 给出 $n$ 个数 $a_1,a_2,...,a_n$ ,将其排为序列 $\{p_i\}$ ,满足 $\{前\ i\ 个数的中位数\}$ 单调不降.求字典序最大的 $\{p_i\}$ . 其 ...

  8. UOJ Test Round #2

    昨天晚上打的这个比赛,简直一颗赛艇啊-- 感觉发挥的并不好.比赛的时候比较紧张,最后一题还脑残写了个离散化结果爆零了,哎我怎么这么逗逼-- 讲讲比赛经过吧. 比赛之前逗逼地以为是8:00开始,然后淡定 ...

  9. Noip模拟62 2021.9.26

    T1 Set 真就随机化拿了$90$?? 不过还是有依据的,毕竟这道题出解的几率很大,随出答案的概率也极大 所以不妨打一个随机化 1 #include<bits/stdc++.h> 2 # ...

随机推荐

  1. python中字典的‘增、删、改、查’

    python 字典的'增.删.改.查' 用 ipython 运行情况如下: #新建字典 In [1]: infos = {'name':'dongge','age':18} In [2]: infos ...

  2. python 列表加法"+"和"extend"的区别

    相同点 : "+"和"extend"都能将两个列表成员拼接到到一起 不同点 :   + : 生成的是一个新列表(id改变) extend : 是将一个列表的成员 ...

  3. Python9-loggin模块-day29

    什么叫日志日志 是用来记录用户行为或者代码的执行过程 # import logging # logging.debug('debug message') #低级别的 排除信息 # logging.in ...

  4. oracle如何保证读一致性 第一弹

    oracle保证读一致性原理   1:undo segment的概念                   当数据库进行修改的时候,需要把保存到以前的old的数据保存到一个地方,然后进行修改,用于保存o ...

  5. LeetCode(274)H-Index

    题目 Given an array of citations (each citation is a non-negative integer) of a researcher, write a fu ...

  6. LeetCode(128) Longest Consecutive Sequence

    题目 Given an unsorted array of integers, find the length of the longest consecutive elements sequence ...

  7. golang(go语言)调试和查看gc信息,以及gc信息解析

    这里记录一下调试golang gc的方法 启用gc打印: # GODEBUG=gctrace=1 go run ./main.go 程序启动后gc将打印如下信息: gc 65 @16.996s 0%: ...

  8. ranorex前一步的操作结果后一步如何调用

     if (!TestSuite.Current.Parameters.ContainsKey("Password"))TestSuite.Current.Parameters.Ad ...

  9. logging模块的作用以及应用场景

    一.python中的logging模块 logging模块定义的函数和类为应用程序和库的开发实现了一个灵活的事件日志系统.logging模块是Python的一个标准库模块,由标准库模块提供日志记录AP ...

  10. 《Spark Python API 官方文档中文版》 之 pyspark.sql (四)

    摘要:在Spark开发中,由于需要用Python实现,发现API与Scala的略有不同,而Python API的中文资料相对很少.每次去查英文版API的说明相对比较慢,还是中文版比较容易get到所需, ...