HDU 4443 带环树形dp
思路:如果只有一棵树这个问题很好解决,dp一次,然后再dfs一次往下压求答案就好啦,带环的话,考虑到环上的点不是
很多,可以暴力处理出环上的信息,然后最后一次dfs往下压求答案就好啦。细节比较多。
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define PLI pair<LL, int>
#define ull unsigned long long
using namespace std; const int N = 1e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + ;
const double eps = 1e-; double ans[N], dp[N], up[N], down[N];
int n, m, tot, head[N], deg[N], edgecnt[N];
bool is[N], vis[N];
vector<int> cir;
struct Edge {
int from, to, nx;
} edge[N<<]; void addEdge(int u, int v) {
edge[tot].from = u;
edge[tot].to = v;
edge[tot].nx = head[u];
head[u] = tot++;
}
void dfs(int u) {
vis[u] = true;
cir.push_back(u);
for(int i = head[u]; ~i; i = edge[i].nx) {
int v = edge[i].to;
if(is[v] || vis[v]) continue;
dfs(v);
}
} void dfs1(int u, int fa) {
edgecnt[u] = ;
for(int i = head[u]; ~i; i = edge[i].nx) {
if(edge[i].to == fa || !is[edge[i].to]) continue;
int v = edge[i].to;
edgecnt[u]++;
dfs1(v, u);
}
dp[u] = 1.0 / (edgecnt[u]+);
if(edgecnt[u]) {
for(int i = head[u]; ~i; i = edge[i].nx) {
if(edge[i].to == fa || !is[edge[i].to]) continue;
int v = edge[i].to;
dp[u] += dp[v] / edgecnt[u];
}
}
} void dfs2(int u, int fa, double val) {
if(!edgecnt[u]) {
ans[u] += val;
return;
}
double sum = ;
for(int i = head[u]; ~i; i = edge[i].nx) {
if(edge[i].to == fa || !is[edge[i].to]) continue;
sum += dp[edge[i].to];
}
if(!fa) {
for(int i = head[u]; ~i; i = edge[i].nx) {
if(edge[i].to == fa || !is[edge[i].to]) continue;
int v = edge[i].to;
if(edgecnt[u] == ) dfs2(v, u, 1.0/(edgecnt[u]+)+val);
else dfs2(v, u, 1.0/(edgecnt[u]+)+val/edgecnt[u]+(sum-dp[v])/(edgecnt[u]+));
}
} else {
for(int i = head[u]; ~i; i = edge[i].nx) {
if(edge[i].to == fa || !is[edge[i].to]) continue;
int v = edge[i].to;
dfs2(v, u, 1.0/(edgecnt[u]+)+val/edgecnt[u]+(sum-dp[v])/edgecnt[u]);
}
}
} void init() {
tot = ; cir.clear();
for(int i = ; i <= n; i++)
head[i]=-, ans[i]=deg[i]=is[i]=vis[i]=;
} int main() {
while(scanf("%d", &n) != EOF && n) {
init();
for(int i = ; i <= n; i++) {
int u, v; scanf("%d%d", &u, &v);
addEdge(u, v); addEdge(v, u);
deg[u]++, deg[v]++;
}
queue<int> que;
for(int i = ; i <= n; i++) {
if(deg[i] == ) {
que.push(i);
is[i] = true;
}
}
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = head[u]; ~i; i = edge[i].nx) {
int v = edge[i].to;
if(is[v]) continue;
deg[v]--, deg[u]--;
if(deg[v] == ) {
is[v] = true;
que.push(v);
}
}
} for(int i = ; i <= n; i++)
if(!is[i] && !vis[i]) dfs(i); int cnt = cir.size();
for(int i = ; i < cnt; i++) {
int root = cir[i];
dfs1(root, );
up[root] = 1.0*/(edgecnt[root]+); down[root] = ;
for(int j = head[root]; ~j; j = edge[j].nx) {
int v = edge[j].to;
if(!is[v]) continue;
up[root] += dp[v]*/(edgecnt[root]+);
}
} for(int i = ; i < cnt; i++) {
double now = up[cir[i]]/;
for(int k = ; k < cnt; k++) {
int j = (i+k)%cnt;
if(k == cnt-) down[cir[j]] += now;
else down[cir[j]] += now*(edgecnt[cir[j]])/(edgecnt[cir[j]]+);
now /= edgecnt[cir[j]]+;
}
now = up[cir[i]]/;
for(int k = ; k < cnt; k++) {
int j = (i-k+cnt)%cnt;
if(k == cnt-) down[cir[j]] += now;
else down[cir[j]] += now*(edgecnt[cir[j]])/(edgecnt[cir[j]]+);
now /= edgecnt[cir[j]]+;
}
}
for(int i = ; i < cnt; i++)
dfs2(cir[i], , down[cir[i]]); sort(ans+, ans++n);
reverse(ans+, ans++n);
double ret = ;
for(int i = ; i <= ; i++)
ret += ans[i];
printf("%.5f\n", ret/n);
}
return ;
} /*
*/
HDU 4443 带环树形dp的更多相关文章
- HDU 4514 - 湫湫系列故事——设计风景线 - [并查集判无向图环][树形DP求树的直径]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...
- hdu 5452 Minimum Cut 树形dp
Minimum Cut Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=54 ...
- HDU 1520 Anniversary party [树形DP]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 题目大意:给出n个带权点,他们的关系可以构成一棵树,问从中选出若干个不相邻的点可能得到的最大值为 ...
- HDU 1011 Starship Troopers 树形DP 有坑点
本来是一道很水的树形DP题 设dp[i][j]表示,带着j个人去攻打以节点i为根的子树的最大收益 结果wa了一整晚 原因: 坑点1: 即使这个节点里面没有守卫,你如果想获得这个节点的收益,你还是必须派 ...
- POJ 2342 &&HDU 1520 Anniversary party 树形DP 水题
一个公司的职员是分级制度的,所有员工刚好是一个树形结构,现在公司要举办一个聚会,邀请部分职员来参加. 要求: 1.为了聚会有趣,若邀请了一个职员,则该职员的直接上级(即父节点)和直接下级(即儿子节点) ...
- hdu 1520Anniversary party(简单树形dp)
Anniversary party Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- Install Air Conditioning HDU - 4756(最小生成树+树形dp)
Install Air Conditioning HDU - 4756 题意是要让n-1间宿舍和发电站相连 也就是连通嘛 最小生成树板子一套 但是还有个限制条件 就是其中有两个宿舍是不能连着的 要求所 ...
- HDU 3586 二分答案+树形DP判定
HDU 3586 『Link』HDU 3586 『Type』二分答案+树形DP判定 ✡Problem: 给定n个敌方据点,1为司令部,其他点各有一条边相连构成一棵树,每条边都有一个权值cost表示破坏 ...
- HDU 3586.Information Disturbing 树形dp 叶子和根不联通的最小代价
Information Disturbing Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/ ...
随机推荐
- 笔记 oracle 创建主键自增长
笔记 (1) 创建表 create table test( id number(18,2) primary key, -- 主键(unique+not null) name varchar2(100) ...
- fopen()、fwrite()、fread()函数使用说明与示例
fopen()函数: 1.作用: 在C语言中fopen()函数用于打开指定路径的文件,获取指向该文件的指针. 2.函数原型: FILE * fopen(const char * path,const ...
- 完美解决github访问速度慢
1. 解决方法 2.解决方法 1. 修改本地hosts文件 windows系统的hosts文件的位置如下:C:\Windows\System32\drivers\etc\hosts mac/linux ...
- 浅谈splay(点的操作)
浅谈splay(点的操作) 一.基本概念 splay本质:二叉查找树 特点:结点x的左子树权值都小于x的权值,右子树权值都大于x的权值 维护信息: 整棵树:root 当前根节点 sz书上所有结点编号 ...
- 【js学习笔记】去除省、市、区、特别行政区、自治区
不是很懂js,以前去除这些省.市.区的时候都是用的分支判断indexOf,如果!=-1则replace一次,今天看同事的代码,发现还有更简单的办法... var areaName = str.repl ...
- Sparse Filtering简介
当前很多的特征学习(feature learning)算法需要很多的超参数(hyper-parameter)调节, Sparse Filtering则只需要一个超参数--需要学习的特征的个数, 所以非 ...
- 渐变色之location概念.
CHENYILONG Blog 渐变色之location概念.全屏幕13-12-22 上午10:18 © chenyilong. Powered by Postach.io Blog
- Python练习-迭代器-模拟cat|grep文件
代码如下: # 编辑者:闫龙 def grep(FindWhat): f=open("a.txt","r",encoding="utf8") ...
- 线段树(dfs序建树加区间更新和单点查询)
题目链接:https://cn.vjudge.net/contest/66989#problem/J 记录一下这道折磨了我一天的题,.... 具体思路: 具体关系可通过dfs序建树,但是注意,在更新以 ...
- 弗罗贝尼乌斯範数(Frobenius norm)
弗罗贝尼乌斯範数 对 p = 2,这称为弗罗贝尼乌斯範数(Frobenius norm)或希尔伯特-施密特範数( Hilbert–Schmidt norm),不过后面这个术语通常只用于希尔伯特空间.这 ...