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/ ...
随机推荐
- 安装lsb_release
lsb_release命令用来查看当前系统的发行版信息(prints certain LSB (Linux Standard Base) and Distribution information.). ...
- Tomcat与Spring中的事件机制详解
最近在看tomcat源码,源码中出现了大量事件消息,可以说整个tomcat的启动流程都可以通过事件派发机制串起来,研究透了tomcat的各种事件消息,基本上对tomcat的启动流程也就有了一个整体的认 ...
- ConcrrentSkipListMap介绍和原理分析
一.前言: JDK为我们提供了很多Map接口的实现,使得我们可以方便地处理Key-Value的数据结构. 当我们希望快速存取<Key, Value>键值对时我们可以使用HashMap. 当 ...
- sklearn评估模型的方法
一.acc.recall.F1.混淆矩阵.分类综合报告 1.准确率 第一种方式:accuracy_score # 准确率import numpy as np from sklearn.metrics ...
- 45、文件过滤器FilenameFilter
文件过滤器FilenameFilter JDK中提供了一个FilenameFilter的接口用来实现文件过滤功能,可以使用这个文件过滤器来实现上一节中的问题. File类中有一个带参数的list方法 ...
- js工作常见问题收集
1. viewport <meta name="viewport" content="width=device-width,initial-scale=1.0,mi ...
- 20165320 第四次实验 Android开发
实验内容: Android程序设计-1 实验要求: - 参考<Java和Android开发学习指南(第二版)(EPUBIT,Java for Android 2nd)>第二十四章: - 参 ...
- 连接数据库及出现System.AccessViolationException错误的解决方法
调试后发现, connection.Open();以后报错,System.AccessViolationException: 尝试读取或写入受保护的内存.这通常指示其他内存已损坏,网上搜了很多都没有作 ...
- python3之pymysql模块
1.python3 MySQL数据库链接模块 PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb. PyMySQL 遵循 Pyt ...
- linux limits研究
---------------------------------------------------------------------------------------------------- ...