hdu 6867 Tree 2020 Multi-University Training Contest 9 dfs+思维
题意:
给你一个由n个点,n-1条有向边构成的一颗树,1为根节点
下面会输入n-1个数,第i个数表示第i+1点的父节点。你可以去添加一条边(你添加的边也是有向边),然后找出来(x,y)这样的成对节点。问你最多能找出来多少对
其中x和y可以相等,且x点要可以到达y点
题解:
根据样例找一下就可以看出来让根节点1和深度最深那个点相连之后能找出来的(x,y)最多
但是又出现一个问题,如果那个最大深度的点不止一个,那么我们要选择那个。如下样例
6
1 1 2 2 3
化成图就是
4、5、6号点都是最深深度的点,且如果你选择4或5和根节点1相连,那么(x,y)的数量是22,如果你选择6点和根节点1相连,那么(x,y)的数量是23
所以最深深度节点有多个我们还需要判断,于是我们先找到所有最深深度的点,然后对它们进行枚举
设最深深度为maxx,你会发现,答案的一部分是maxx*(n-1)+maxx
maxx*(n-1):就是我们找到的那个最深深度那个点和根节点1构成的那个链,那个链上的所有点都可以到达其他顶点,所以就是这个答案
maxx:因为x和y可以相等,所以就加上这个链上的所有点
对于其他(x,y)我么可以这样找,我们还用上面的例子,我们找最长链为1,3,6
我们首先把1,3,6这条边标记,然后把没有标记链的红色权值加起来就行了,红色权值的构成就是每一个点最开始红色权值是1,然后子节点为父节点贡献它的权值,子节点向父节点贡献权值就相当于(2,4)和(2,5)。
它们本身最开始的权值1就相当于(4,4),(5,5),(2,2)
但是最后你会发现这样会TLE
TLE代码:
1 #include<stack>
2 #include<queue>
3 #include<map>
4 #include<cstdio>
5 #include<cstring>
6 #include<iostream>
7 #include<algorithm>
8 #include<vector>
9 #define fi first
10 #define se second
11 #define pb push_back
12 using namespace std;
13 typedef long long ll;
14 const int maxn=5e5+10;
15 const int mod=1e9+7;
16 const double eps=1e-8;
17 ll vis[maxn],val[maxn],fa[maxn],test[maxn],head[maxn],summ[maxn];
18 queue<ll>r;
19 vector<ll>w[maxn];
20 void add_edge(ll x,ll y)
21 {
22 w[x].push_back(y);
23 }
24 void dfs(ll x)
25 {
26 ll len=w[x].size();
27 for(ll i=0;i<len;++i)
28 {
29 ll y=w[x][i];
30 dfs(y);
31 summ[x]+=summ[y];
32 }
33 }
34 int main()
35 {
36 ll t;
37 scanf("%lld",&t);
38 while(t--)
39 {
40 while(!r.empty())
41 r.pop();
42 memset(vis,0,sizeof(vis));
43 memset(test,0,sizeof(test));
44 ll n,x,total,maxx=1,pos=1,index=1;
45 scanf("%lld",&n);
46 for(int i=1;i<=n;++i)
47 w[i].clear();
48 fa[1]=0;
49 val[1]=1;
50 summ[1]=1;
51 for(ll i=2; i<=n; ++i)
52 {
53 summ[i]=1;
54 scanf("%lld",&fa[i]);
55 add_edge(fa[i],i);
56 val[i]=val[fa[i]]+1;
57 test[fa[i]]=i;
58 if(maxx<val[i])
59 {
60 maxx=val[i];
61 pos=i;
62 }
63 }
64 dfs(1);
65 // for(ll i=2; i<=n; ++i)
66 // {
67 // if(test[i]==0)
68 // {
69 // head[index++]=i;
70 // ll temp=i;
71 // while(fa[temp])
72 // {
73 // summ[fa[temp]]+=summ[temp];
74 // temp=fa[temp];
75 // }
76 // }
77 // }
78 for(ll i=2; i<=n; ++i)
79 {
80 if(val[i]==maxx)
81 {
82 r.push(i);
83 }
84 }
85 ll result=0;
86 ll bloo=maxx*(n-1)+maxx;
87 //printf("%d %lld\n",r.size(),maxx*(n-1)+n);
88 while(!r.empty())
89 {
90 ll temp=r.front(),sum=bloo;
91 while(temp)
92 {
93 vis[temp]=1;
94 temp=fa[temp];
95 }
96 temp=r.front();
97 for(ll i=2;i<=n;++i)
98 {
99 if(vis[i]==0)
100 {
101 sum+=summ[i];
102 // if(temp==8)
103 // {
104 // printf("%lld %lld\n",i,summ[i]);
105 // }
106 }
107
108 }
109 result=max(result,sum);
110 temp=r.front();
111 r.pop();
112 while(temp)
113 {
114 vis[temp]=0;
115 temp=fa[temp];
116 }
117 }
118 printf("%lld\n",result);
119 }
120 return 0;
121 }
122 /*
123
124 */
然后就想办法优化,你可以先把所有节点的红色权值都算出来,然后把这些值都加起来,使用变量k保存,然后我们用一个数组变量
sumi表示从根节点到i节点所有节点红色权值的和
对于我们枚举到的一个最深深度节点i,我们可以使用k-sum[i]来找出来排除最长链之外的其他点能找到的(x,y)
然后再加上之前的maxx*(n-1)+maxx就行了
AC代码:
1 #include <cstdio>
2 #include <algorithm>
3 #include <iostream>
4 #include <vector>
5 #include <map>
6 #include <queue>
7 #include <set>
8 #include <ctime>
9 #include <cstring>
10 #include <cstdlib>
11 #include <math.h>
12 using namespace std;
13 typedef long long ll;
14 const ll N = 2009;
15 const ll maxn = 1e6 + 20;
16 const ll mod = 1000000007;
17 ll inv[maxn], vis[maxn], dis[maxn], head[maxn], dep[maxn], out[maxn];
18 ll fac[maxn], a[maxn], b[maxn], c[maxn], pre[maxn], cnt, sizx[maxn];
19 vector<ll> vec;
20 char s[maxn];
21 ll sum[maxn];
22 ll max(ll a, ll b) { return a > b ? a : b; }
23 ll min(ll a, ll b) { return a < b ? a : b; }
24 ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
25 ll lcm(ll a, ll b) { return a * b / gcd(a, b); }
26 map<ll, ll> mp;
27 ll ksm(ll a, ll b)
28 {
29 a %= mod;
30 ll ans = 1ll;
31 while (b)
32 {
33 if (b & 1)
34 ans = (ans * a) % mod;
35 a = (a * a) % mod;
36 b >>= 1ll;
37 }
38 return ans;
39 }
40 ll lowbit(ll x)
41 {
42 return x & (-x);
43 }
44 ll dp[maxn][3];
45 queue<int> q;
46 struct node
47 {
48 ll v, nex;
49 } edge[maxn << 1];
50 void add(ll u, ll v)
51 {
52 edge[cnt].v = v, edge[cnt].nex = head[u];
53 head[u] = cnt++;
54 }
55 void dfs1(ll u, ll fa)
56 {
57 dep[u] = dep[fa] + 1;
58 sizx[u] = 1ll;
59 for (ll i = head[u]; ~i; i = edge[i].nex)
60 {
61 ll v = edge[i].v;
62 if (v != fa)
63 {
64 dfs1(v, u);
65 sizx[u] += sizx[v];
66 }
67 }
68 }
69 void dfs2(ll u, ll fa)
70 {
71 sum[u] = sum[u] + sum[fa] + sizx[u];
72 for (ll i = head[u]; ~i; i = edge[i].nex)
73 {
74 ll v = edge[i].v;
75 if (v != fa)
76 dfs2(v, u);
77 }
78 }
79 int main()
80 {
81 ll t;
82 scanf("%lld", &t);
83 while (t--)
84 {
85 vec.clear();
86 cnt = 0;
87 ll n, m = 0, fa, k = 0, maxx = 0, ans = 0;
88 scanf("%lld", &n);
89 for (ll i = 0; i <= n; i++)
90 sum[i] = out[i] = sizx[i] = dep[i] = 0, head[i] = -1;
91 for (ll i = 2; i <= n; i++)
92 {
93 scanf("%lld", &fa), out[fa]++;
94 add(fa, i), add(i, fa);
95 }
96 dfs1(1, 0);
97 dfs2(1, 0);
98 for (ll i = 1; i <= n; i++)
99 {
100 k += sizx[i];
101 if (!out[i])
102 vec.push_back(i);
103 }
104 m = vec.size();
105 for (ll i = 0; i < m; i++)
106 {
107 ll res = (dep[vec[i]]) * (n - 1) - sum[vec[i]] + dep[vec[i]];
108 ans = max(ans, res + k);
109 }
110 printf("%lld\n", ans);
111 }
112 }
hdu 6867 Tree 2020 Multi-University Training Contest 9 dfs+思维的更多相关文章
- hdu 6394 Tree (2018 Multi-University Training Contest 7 1009) (树分块+倍增)
链接: http://acm.hdu.edu.cn/showproblem.php?pid=6394 思路:用dfs序处理下树,在用分块,我们只需要维护当前这个点要跳出这个块需要的步数和他跳出这个块去 ...
- hdu 4930 Fighting the Landlords--2014 Multi-University Training Contest 6
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4930 Fighting the Landlords Time Limit: 2000/1000 MS ...
- HDU 6143 - Killer Names | 2017 Multi-University Training Contest 8
/* HDU 6143 - Killer Names [ DP ] | 2017 Multi-University Training Contest 8 题意: m个字母组成两个长为n的序列,两序列中 ...
- HDU 6074 - Phone Call | 2017 Multi-University Training Contest 4
看标程的代码这么短,看我的.... 难道是静态LCA模板太长了? /* HDU 6074 - Phone Call [ LCA,并查集 ] | 2017 Multi-University Traini ...
- HDU 6068 - Classic Quotation | 2017 Multi-University Training Contest 4
/* HDU 6068 - Classic Quotation [ KMP,DP ] | 2017 Multi-University Training Contest 4 题意: 给出两个字符串 S[ ...
- HDU 6076 - Security Check | 2017 Multi-University Training Contest 4
/* HDU 6076 - Security Check [ DP,二分 ] | 2017 Multi-University Training Contest 4 题意: 给出两个检票序列 A[N], ...
- HDU 6071 - Lazy Running | 2017 Multi-University Training Contest 4
/* HDU 6071 - Lazy Running [ 建模,最短路 ] | 2017 Multi-University Training Contest 4 题意: 四个点的环,给定相邻两点距离, ...
- HDU 6078 - Wavel Sequence | 2017 Multi-University Training Contest 4
/* HDU 6078 - Wavel Sequence [ DP ] | 2017 Multi-University Training Contest 4 题意: 给定 a[N], b[M] 要求满 ...
- HDU 6070 - Dirt Ratio | 2017 Multi-University Training Contest 4
比赛时会错题意+不知道怎么线段树维护分数- - 思路来自题解 /* HDU 6070 - Dirt Ratio [ 二分,线段树 ] | 2017 Multi-University Training ...
随机推荐
- 诸葛 VS 庞统,拿下 Paxos 共识算法
前言 分布式确实是一个有趣的话题,只要你留心观察,分布式在生活中无处不在. 悟空哥最开始学习分布式是从一篇非常用心写的技术征文开始的,而且这篇文章获得了征文第一名,在此感谢掘金社区提供的平台.想学习的 ...
- 安装Tomcat 9
文章目录 访问Tomcat官网 选择下载所需的软件包 安装Tomcat 测试安装 访问Tomcat官网 Tomcat官方的下载地址为:https://tomcat.apache.org/downloa ...
- ctfshow—web—web2
打开靶机,根据提示是SQL注入 打开后看到登录窗口 方法一.手工注入 抓取数据包 开始SQL注入测试 利用万能密码,登录成功 查看回显位置 查询数据库 查询数据库内数据表 如果想整齐一点显示可以添加g ...
- 02. struts2中Action名称的搜索顺序
搜索顺序 获得请求路径的URI,例如URL为:http://localhost:8080/struts2/path1/path2/path3/student.action 首先寻找namespace为 ...
- HTML部分
1.说一下<label>标签的用法 label标签主要是方便鼠标点击使用,扩大可点击的范围,增强用户操作体验 2.说一下事件代理? 事件委托是指将事件绑定到目标元素的父元素上,利用冒泡机制 ...
- cisco asa 5525 思科防火墙设置拨号访问内网以及外网
WZ-2A10-SAS5525-0938# show running-config : Saved : : Serial Number: FCH17307098 : Hardware: ASA5525 ...
- Xamarin.Forms: 无限滚动的ListView(懒加载方式)
说明 在本博客中,学习如何在Xamarin.Forms应用程序中设计一个可扩展的无限滚动的ListView.这个无限滚动函数在默认的Xamarin.Forms不存在,因此我们需要为此添加插件.在这里我 ...
- 网易新闻App架构重构实践:DDD正走向流行
网易新闻App架构重构实践:DDD正走向流行 https://mp.weixin.qq.com/s/FdwrT_xn3CQqpWoRVBttvQ 小智 InfoQ 2020-05-14 作者 | 小智 ...
- wireshark使用手册
Wireshark的过滤器 使用Wireshark时最常见的问题,是当您使用默认设置时,会得到大量冗余信息,以至于很难找到自己需要的部分. 过犹不及. 这就是为什么过滤器会如此重要.它们可以帮助我们在 ...
- EF Code First 无法加载指定的元数据资源
是由属于一般出现这个错误是由于App.config里面配置错误,DB First 是不一样的. 配置文件不止一个地方··多查查其他项目有没有.