Tree and Permutation (HDU 6446) 题解
// 昨天打了一场网络赛,表现特别不好,当然题目难度确实影响了发挥,但还是说明自己太菜了,以后还要多多刷题。
2018 CCPC 网络赛 I - Tree and Permutation
简单说明一下题意,给出一个1,2,3...N的排列,显然全部共有N!种排列,每种排列的数字代表树上的一个结点,设Pi是其中第i种排列的相邻数字表示的结点的距离之和,让我们求sum(Pi)(1<=i<=N!)。
可以设dis(i, j)为树上任意两点间的最短距离,稍加分析一下容易得到所求答案为 (N-1)! * sum(dis(i, j))。对于dis(i, j)很容易想到用Floyd算法来求,但题目数据量为1e5很明显复杂度O(n^3)的算法肯定超时。由于这是一棵树,dis(i, j)的最短路径是唯一的(不存在环),那么对于相邻结点u, v,可以发现边(u, v)走过的次数为左边结点数量*右边结点数量。现在大概就是一道树形dp的题了,剩下的就是代码实现了。AC代码如下:
#include <cstdio>
#include <cstring>
using namespace std; const int maxn = ;
const int mod = 1e9+; int head[maxn], cnt;
struct Edge{
int to, nxt, w;
Edge(){}
Edge(int _to, int _nxt, int _w): to(_to), nxt(_nxt), w(_w){}
};
Edge edge[maxn*]; // 注意要开两倍边的空间,加边时以无向图处理,加了双向边 int n, child[maxn];
long long ans;
long long fact[maxn];
void pre()
{
fact[] = ;
for(int i=;i<maxn;i++)
fact[i] = fact[i-] * i % mod;
} void init()
{
cnt = ;
memset(head, -, sizeof(head));
memset(child, , sizeof(child));
} void add(int from, int to, int weight)
{
edge[cnt] = Edge(to, head[from], weight);
head[from] = cnt++;
} void dfs(int u, int fa)
{
child[u] = ;
for(int i=head[u];~i;i=edge[i].nxt)
{
int v = edge[i].to;
if(v!=fa)
{
dfs(v, u);
child[u] += child[v];
ans += (long long)child[v]*(n-child[v])*edge[i].w%mod; // 没有强制转换相乘会溢出,WA WA大哭。。。
if(ans>mod) ans -= mod;
}
}
} int main()
{
pre(); int u, v, dis;
while(~scanf("%d", &n))
{
init();
for(int i=;i<n;i++)
{
scanf("%d %d %d", &u, &v, &dis);
add(u, v, dis);
add(v, u, dis);
} ans = ;
dfs(, -);
printf("%lld\n", *ans*fact[n-]%mod); }
return ;
}
// 比赛的时候用的vector存邻接链表,瞎搞了半天用map<pair<int,int>, int>存dis(u,v),交上去一直TLE,不明白怎么回事,昨晚调了半天又一直ML(Memory Limit)
// 上网查了一下说是vector跟map内存没有释放什么的,反正到现在还没弄明白。。。以后还是用链式前向星吧
update补充:
经过不懈探索,用邻接链表实现了AC。舍弃了map存树上的边的方法,将结点与边放到pair构成的vetor里
typedef pair<int, int> P; // first 为结点,second为边
vector<P> G[maxn]; // G[u]存相邻结点的信息:G[u][i].second 为u到结点G[u][i].first的边
这种写法应该不常见,以后还是要尽量避免使用vector。至于释放vector的内存(不只是清空),我尝试了以下三种操作都可以AC,不确定孰优孰劣。以后学习C++再好好研究一番。
- memset(G, 0, sizeof(G));
for(int i=1;i<=n;i++) G[i].clear();
for(int i=1;i<=n;i++) vector<P>().swap(G[i]);
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <map>
using namespace std; const int maxn = ;
const int mod = 1e9+;
typedef long long ll;
typedef pair<int, int> P; vector<P> G[maxn];
ll fact[maxn], ans;
int n, child[maxn]; void dfs(int u, int fa)
{
// printf("%d->%d\n", fa, u);
child[u] = ;
int len = G[u].size();
for(int i=;i<len;i++)
{
int v = G[u][i].first;
if(v!=fa)
{
dfs(v, u);
child[u] += child[v];
ans += (long long)child[v]*(n-child[v])*G[u][i].second % mod;
ans %= mod;
}
} } int main()
{
fact[] = ;
for(int i=;i<maxn;i++)
{
fact[i] = fact[i-] * i % mod;
// printf("%d %lld\n", i, fact[i]);
} int u, v, d;
while(~scanf("%d", &n))
{
memset(child, , sizeof(child));
for(int i=;i<n;i++)
{
scanf("%d %d %d", &u, &v, &d);
G[u].push_back(P(v, d));
G[v].push_back(P(u, d));
}
ans = ;
dfs(, -);
printf("%lld\n", *ans*fact[n-]%mod); for(int i=;i<=n;i++) //G[i].clear();
vector<P>().swap(G[i]);
}
return ;
}
以后还要多多刷题呀~~~
Tree and Permutation (HDU 6446) 题解的更多相关文章
- 2018中国大学生程序设计竞赛 - 网络选拔赛 hdu Tree and Permutation 找规律+求任意两点的最短路
Tree and Permutation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Oth ...
- HDU6446 Tree and Permutation(树上DP)
传送门:点我 Tree and Permutation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (J ...
- 2018中国大学生程序设计竞赛 - 网络选拔赛 1009 - Tree and Permutation 【dfs+树上两点距离和】
Tree and Permutation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Oth ...
- hdu6446 Tree and Permutation 2018ccpc网络赛 思维+dfs
题目传送门 题目描述:给出一颗树,每条边都有权值,然后列出一个n的全排列,对于所有的全排列,比如1 2 3 4这样一个排列,要算出1到2的树上距离加2到3的树上距离加3到4的树上距离,这个和就是一个排 ...
- Tree and Permutation
Tree and Permutation 给出一个1,2,3...N的排列,显然全部共有N!种排列,每种排列的数字代表树上的一个结点,设Pi是其中第i种排列的相邻数字表示的结点的距离之和,让我们求su ...
- Tree and Permutation dfs hdu 6446
Problem Description There are N vertices connected by N−1 edges, each edge has its own length.The se ...
- HDU - 6446 Tree and Permutation
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6446 本题是一个树上的问题——DFS. 一棵N个结点的树,其结点为1~N.树具有N-1条边,每一条边具有 ...
- (1009) HDU 6446 Tree and Permutation(规律+树上各个点的距离和)
题意: 给一棵N个点的树,对应于一个长为N的全排列,对于排列的每个相邻数字a和b,他们的贡献是对应树上顶点a和b的路径长,求所有排列的贡献和. 分析: 经过简单的分析可以得知,全部的贡献其实相当与(这 ...
- HDU 6446 Tree and Permutation(赛后补题)
>>传送门<< 分析:这个题是结束之后和老师他们讨论出来的,很神奇:刚写的时候一直没有注意到这个是一个树这个条件:和老师讨论出来的思路是,任意两个结点出现的次数是(n-1)!, ...
随机推荐
- Unity实现Android端视频播放
本文只讲Android短的视频播放 实现方式 使用Handheld.PlayFullScreenMovie(),这个函数实现.具体如下: 1.创建StreamingAssets文件夹,此文件夹放入视频 ...
- css3的选择器
先来做一下准备工作 页面的效果: 看到上面的框框了吗?我们就是通过给这些框框添加背景色的方式,来让大家,了解css3的选择器的效果,下面正式开始: 关联选择器 E1~E2 选择 E1 后面的兄弟 E2 ...
- 了解JNI技术
在线文库系统用到了Jacob,它是基于JNI技术实现的,通过调用MS Office的Com接口实现,我这里对JNI技术进行一个学习. 基本上JNI技术相当于一个代理,因为java的跨平台特性,所以它自 ...
- 解决VS2012新建MVC4等项目时,收到此模板加载程序集“NuGet.VisualStudio.Interop…”的错误
1.错误如图所示: 2.不管是VS2012,还是2013如果开始没安装Nuget包都或报这个错,因为VS2012就已经全面切换到使用NuGet这个第三方开源工具来管理项目包和引用模块了,使用VS201 ...
- Theorem、Proposition、Lemma和Corollary等的解释与区别
Theorem:定理.是文章中重要的数学化的论述,一般有严格的数学证明. Proposition:可以翻译为命题,经过证明且interesting,但没有Theorem重要,比较常用. Lemma:一 ...
- ERROR 1872
解决 > start slave; ERROR (HY000): Slave failed to initialize relay log info structure from the rep ...
- Emacs基本操作说明
- (转)HttpURLConnection中设置网络超时
转:http://www.xd-tech.com.cn/blog/article.asp?id=37 Java中可以使用HttpURLConnection来请求WEB资源.HttpURLConnect ...
- 十条服务器端优化Web性能的技巧总结
原文地址:http://www.jb51.net/yunying/452723.html 提高 web 应用的性能从来没有比现在更重要过.网络经济的比重一直在增长:全球经济超过 5% 的价值是在因特网 ...
- 依赖注入(DI)
Spring依赖注入(DI)的三种方式,分别为: 1. 接口注入 2. Setter 方法注入 3. 构造方法注入 依赖注入是一种思想,或者说是一种设计模式,在java中是通过反射机制实现,与具 ...