省选一试后的第一篇blog!

Description

  Z国坐落于遥远而又神奇的东方半岛上,在小Z的统治时代,公路成为这里主要的交通手段。Z国共有n座城市,一些城市之间由双向的公路所连接。非常神奇的是Z国的每个城市所处的经度都不相同,并且最多只和一个位于它东边的城市直接通过公路相连。Z国的首都是Z国政治经济文化旅游的中心,每天都有成千上万的人从Z国的其他城市涌向首都。为了使Z国的交通更加便利顺畅,小Z决定在Z国的公路系统中确定若干条规划路线,将其中的公路全部改建为铁路。我们定义每条规划路线为一个长度大于1的城市序列,每个城市在该序列中最多出现一次,序列中相邻的城市之间由公路直接相连(待改建为铁路)。并且,每个城市最多只能出现在一条规划路线中,也就是说,任意两条规划路线不能有公共部分。当然在一般情况下是不可能将所有的公路修建为铁路的,因此从有些城市出发去往首都依然需要通过乘坐长途汽车,而长途汽车只往返于公路连接的相邻的城市之间,因此从某个城市出发可能需要不断地换乘长途汽车和火车才能到达首都。我们定义一个城市的“不便利值”为从它出发到首都需要乘坐的长途汽车的次数,而Z国的交通系统的“不便利值”为所有城市的不便利值的最大值,很明显首都的“不便利值”为0。小Z想知道如何确定规划路线修建铁路使得Z国的交通系统的“不便利值”最小,以及有多少种不同的规划路线的选择方案使得“不便利值”达到最小。当然方案总数可能非常大,小Z只关心这个天文数字modQ后的值。注意:规划路线1-2-3和规划路线3-2-1是等价的,即将一条规划路线翻转依然认为是等价的。两个方案不同当且仅当其中一个方案中存在一条规划路线不属于另一个方案。

Input

  第一行包含三个正整数N、M、Q,其中N表示城市个数,M表示公路总数,N个城市从1~N编号,其中编号为1的是首都。Q表示上文提到的设计路线的方法总数的模数。接下来M行,每行两个不同的正数ai、bi表示有一条公路连接城市ai和城市bi。输入数据保证一条公路只出现一次。

Output

  包含两行。第一行为一个整数,表示最小的“不便利值”。第二行为一个整数,表示使“不便利值”达到最小时不同的设计路线的方法总数modQ的值。如果某个城市无法到达首都,则输出两行-1。

Sample Input

  5 4 100
  1 2
  4 5
  1 3
  4 1

Sample Output

  1
  10

HINT

  对于100%的数据,满足1≤N,M≤100000,1≤Q≤120000000,1≤ai,bi≤N。

Solution

  题面描述得相当别扭啊,小C也是看过discuss后才知道它给的是一座森林。

  正常来说学过树链剖分的人只要看到这一条件,题目就已经做完了。

  题目实际上要我们求的是,求一棵树的树链剖分方案,使得所有点到根的路径上所走的轻边数量的最大值最小。

  学过树链剖分的人都应该知道,如果按照重链剖分(即重边连向结点更多的子树)来划分一棵树,那么从某个点出发走到根节点最多只要走logN条重链。

  树剖复杂度的证明在此提一下,其实也很简单,设x个结点组成的树中,所有点到根路径上轻边数量最大值的最大值为f(x)。

  那么就有,由于f(x)是递增的,所以f(x)必定是从f((x-1)/2)+1转移得到的。

  所以转移式化简就是:,很显然f(N)是logN级别的。

  因此答案最大不会超过logN,而且这样形态的树是一棵二叉树。

  但实际上这道题所说的链剖不是真正意义上的链剖,划分出来的路径是可以拐弯的,因此答案会比logN更小一些,实际上在树的形态是三叉树的情况下答案达到最大,大概是log_3(N)级别。

  然后知道了以上这些结论我们可以非常容易地写出DP的状态和转移方程:

  设f[i][j][0/1]表示在结点i的子树中,答案为j,且该子树能否继续向上连边的链剖方案数。转移花log^2随便转移一下就行。

  最后判断答案的时候简单地根据该处的DP值是否为0来取最小值是不可行的,因为方案数很可能对Q取模等于0,所以这里有一个小技巧,就是方案数为Q的倍数的时候,将对Q取模的值设为Q即可。

  时间复杂度

#include <cstdio>
#include <algorithm>
#include <cstring>
#define ll long long
#define MN 100005
#define MS 12
using namespace std;
struct edge{int nex,to;}e[MN<<];
int n,m,mod,pin;
int hr[MN],f[MN][][MS]; inline int read()
{
int n=,f=; char c=getchar();
while (c<'' || c>'') {if(c=='-')f=-; c=getchar();}
while (c>='' && c<='') {n=n*+c-''; c=getchar();}
return n*f;
} inline void rw(int& x,int y) {x+=y; if(x>mod)x-=mod;}
inline int modu(ll x) {return !x?:(x-)%mod+;}
inline void ins(int x,int y) {e[++pin]=(edge){hr[x],y}; hr[x]=pin;} void dfs(int x,int fat)
{
register int i,j,k;
int g[][MS],h[][MS+];
memset(g,,sizeof(g));
memset(h,,sizeof(h));
g[][]=;
for (i=hr[x];i;i=e[i].nex)
{
if (e[i].to==fat) continue;
dfs(e[i].to,x);
for (j=;j<MS;++j)
for (k=;k<MS;++k)
{
rw(h[][max(j+,k)],modu(1LL*g[][k]*(f[e[i].to][][j]+f[e[i].to][][j])));
rw(h[][max(j,k)],modu(1LL*g[][k]*f[e[i].to][][j]));
rw(h[][max(j+,k)],modu(1LL*g[][k]*(f[e[i].to][][j]+f[e[i].to][][j])));
rw(h[][max(j,k)],modu(1LL*g[][k]*f[e[i].to][][j]));
rw(h[][max(j+,k)],modu(1LL*g[][k]*(f[e[i].to][][j]+f[e[i].to][][j])));
}
for (j=;j<MS;++j)
g[][j]=h[][j],h[][j]=,
g[][j]=h[][j],h[][j]=,
g[][j]=h[][j],h[][j]=;
}
for (i=;i<MS;++i)
f[x][][i]=g[][i],rw(f[x][][i],g[][i]),f[x][][i]=g[][i];
} int main()
{
register int i,x,y;
n=read(); m=read(); mod=read();
if (m!=n-) return *printf("-1\n-1");
for (i=;i<=m;++i)
x=read(),y=read(),
ins(x,y),ins(y,x);
dfs(,);
for (i=;i<MS;++i)
if (f[][][i]||f[][][i])
return *printf("%d\n%d",i,(f[][][i]+f[][][i])%mod);
}

Last Word

  心血来潮写了一下小D的mint,交上去竟然T了,好感度--,表示这模板不是很想再用了。

[BZOJ]1063 道路设计(Noi2008)的更多相关文章

  1. BZOJ 1063 道路设计NOI2008

    http://www.lydsy.com/JudgeOnline/problem.php?id=1063 题意:给你一棵树,也有可能是不连通的,把树分成几个链,求每个点到根经过的最大链数最小,而且要输 ...

  2. BZOJ 1063 道路设计(树形DP)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1063 题意:给出一个无环图( 也就是树,但是也有可能是森林),代表一个国家的城市.1是首 ...

  3. 【NOI题解】【bzoj题解】NOI2008 bzoj1063 道路设计

    @ACMLCZH学长出的毒瘤题T3.再也不是“善良”的出题人了. 题意:bzoj. 题解: 经典的树形DP题目,屡见不鲜了,然而我还是没有写出来. 这一类的题目有很多,例如这里的C题. 主要套路是把对 ...

  4. bzoj 1064【noi2008】假面舞会

    题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1064 给一个有向图染色,每个点的后继必须相同,问至少&至多有多少种染色方案 sol: ...

  5. 【BZOJ】1061: [Noi2008]志愿者招募

    题解 可能是世界上最裸的一个单纯形 (话说全幺模矩阵是啥我到现在都不知道) 假装我们已经看过了算导,或者xxx的论文,知道了单纯形是怎么实现的 扔一个blog走掉..https://www.cnblo ...

  6. 【BZOJ】1064: [Noi2008]假面舞会(判环+gcd+特殊的技巧)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1064 表示想到某一种情况就不敢写下去了.... 就是找环的gcd...好可怕.. 于是膜拜了题解.. ...

  7. 【BZOJ】1061: [Noi2008]志愿者招募(费用流+数学)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1061 好神的一题! 学会了一种建模方式: 当方程组内的任意变量都在其中两个方程出现且一正一负,可以建 ...

  8. dp专练

    dp练习. codevs 1048 石子归并 区间dp #include<cstdio> #include<algorithm> #include<cstring> ...

  9. BZOJ1000-1099板刷计划+一句话题解 73/100

    1000-1009 1000A+B Problem 这个还要写??? 1001 狼抓兔子 平面图最小割转化为对偶图最短路 #include<bits/stdc++.h> #define i ...

随机推荐

  1. aws中的路由表

    参考官方文档: 由表中包含一系列被称为路由的规则,可用于判断网络流量的导向目的地. 在您的 VPC 中的每个子网必须与一个路由表关联:路由表控制子网的路由.一个子网一次只能与一个路由表关联,但您可以将 ...

  2. Flask 扩展 Flask-PyMongo

    安装 pip install Flask-PyMongo 初始化Pymongo实例 from flask import Flask from flask.ext.pymongo import PyMo ...

  3. 自己写编程语言-m语言

    一直对技术有很强的兴趣,终于,决定要写自己的语言(m语言).那就先从最简单的开始:解释执行器. 一套完整的语言包含的肯定不止解释执行器了,还要有编译器和IDE,也就还要有语法高亮.智能提示等,不过还没 ...

  4. OO第一次总结

    第一次作业: 第一次作业的指导书发下来之后我按着上面的步骤一步一步的做了之后发现项目拉下来了,怎么开始码代码呢...然后在舍友的帮助下才知道怎么建包建类,然后对Java的语法又不是很了解,于是就先把C ...

  5. linux系统命令学习系列-例行任务管理at命令

    先来复习一下上节内容: 切换用户身份命令su 以root身份执行操作命令sudo 作业:给user1配置sudo权限,不用密码,可执行useradd命令 在/etc/sudoers文件中添加如下配置项 ...

  6. 剑指offer-第一个只出现一次的字符

    题目描述 在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置   解题思路 由于char类型一共有256种可能,所以开辟一个数组ha ...

  7. Linux入门:增加用户,并赋予权限

    一.增加用户 1.增加用户,并指定主目录 # useradd –d /usr/sam -m sam此命令创建了一个用户sam,其中-d和-m选项用来为登录名sam产生一个主目录/usr/sam(/us ...

  8. Jmeter入门(01)Jmeter的下载和安装

    一.什么是Jmeter 1.一款优秀的.开源的.免费的.功能测试和性能测试 工具 Jmeter ,使用Java开发的一款优秀的开源免费测试工具,主要用来做功能测试和性能测试(压力测试/负载测试),用J ...

  9. oracle中求1到100之间的质数和

    declare i number:=1; j number:=0; sum1 number:=0;begin while(i<100) loop i:=i+1; j:=2; while(mod( ...

  10. Java:Linux上java -jar xxx.jar命令执行jar包时出现Error: Invalid or corrupt jarfile xxx.jar解决方案

    背景: 从ftp上上传jar包到linux上,之后在linux上通过ftp命令下载jar包文件,开始执行Java-jar,一直提示错误:Error: Invalid or corrupt jarfil ...