codeforces 757F Team Rocket Rises Again(最短路+支配树)
来源:互联网 发布:如何下载bilibili mac 编辑:程序博客网 时间:2024/06/07 18:48
今天刚刚看了支配树,然而恕我太弱并没有看明白Lengauer-Tarjan算法,比较懵QAQ……不过我倒是学会了在DAG上构建支配树,就贴一道简单题过来吧O(∩_∩)O。
如何在DAG上求支配树?
有向无环图(DAG)里我们可以按照拓扑序构建支配树。
假设当前我们构造到拓扑序中第x个节点编号为v,那么此时支配树中已经有拓扑序第1~x-1个节点了。考虑所有能够直接到达v的节点,对于这些节点我们求出它们在支配树上的最近公共祖先Lca(所以要反向建一份图g2),这个点Lca就是点v在支配树上的父亲。
这样,支配树就建好了
用倍增求LCA的话,时间复杂度是O((n+m)log2n)。
题目链接:codeforces 757 F
题解:这个题的话,跑出最短路图,再在最短路图上建支配树,求最大的子树大小。 code(有参考网上神犇们的代码)
#include<iostream>#include<cstdio> #include<cstring>#include<algorithm>#include<cmath>#define inf 1LL<<60using namespace std;inline int read(){ char c=getchar(); int num=0,f=1; while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); } while (c<='9'&&c>='0') { num=num*10+c-'0'; c=getchar(); } return num*f;}struct edge{ int to,ne; long long val;}e[600005],g1[600005],g2[600005];//e[]是原图,g1[]是最短路图,g2[]和g1[]边的方向相反int head[200005],head1[200005],head2[200005];int que[4000005];int d[200005],deep[200005],siz[200005];int fa[200005][22];int S,n,m,tot,tot1,tot2,ans;bool vis[200005];long long dis[200005];void push(int x,int y,long long val){ e[++tot].to=y; e[tot].val=val; e[tot].ne=head[x]; head[x]=tot;}void push1(int x,int y){ g1[++tot1].to=y; g1[tot1].ne=head1[x]; head1[x]=tot1;}void push2(int x,int y){ g2[++tot2].to=y; g2[tot2].ne=head2[x]; head2[x]=tot2;}void spfa(int S){ for (int i=1;i<=n;i++) dis[i]=inf; int h=0,t=1; dis[S]=0,vis[S]=true,que[t]=S; while (h<t) { int now=que[++h]; for (int i=head[now];i;i=e[i].ne) { int v=e[i].to; if (dis[v]>dis[now]+e[i].val) { dis[v]=dis[now]+e[i].val; if (!vis[v]) vis[v]=true,que[++t]=v; } } vis[now]=false; }}void dfs1(int now) //找出最短路图中的边{ vis[now]=true; for (int i=head[now];i;i=e[i].ne) { int v=e[i].to; if (dis[v]==dis[now]+e[i].val) { push1(now,v); push2(v,now); d[v]++; if (!vis[v]) dfs1(v); } }}void dfs2(int now) //求出支配树各节点的size,更新答案{ siz[now]=1; for (int i=head[now];i;i=e[i].ne) { int v=e[i].to; dfs2(v); siz[now]+=siz[v]; } if (now!=S) ans=max(ans,siz[now]);}int lca(int x,int y) //倍增lca{ if (x==y) return x; if (deep[x]<deep[y]) swap(x,y); for (int i=20;i>=0;i--) if (deep[fa[x][i]]>=deep[y]) x=fa[x][i]; if (x==y) return x; for (int i=20;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0];}void topsort() //拓扑排序{ int h=0,t=1; que[t]=S,deep[S]=1; while (h<t) { int now=que[++h]; for (int i=head1[now];i;i=g1[i].ne) { int v=g1[i].to; d[v]--; if (!d[v]) { que[++t]=v; int Lca=0; for (int j=head2[v];j;j=g2[j].ne) { int vv=g2[j].to; if (!Lca) Lca=vv; else Lca=lca(vv,Lca); } //找到v的支配点Lca,把v点加入支配树里 push(Lca,v,0); fa[v][0]=Lca,deep[v]=deep[Lca]+1; for (int j=1;j<=20;j++) fa[v][j]=fa[fa[v][j-1]][j-1]; } } }}int main(){ n=read(); m=read(); S=read(); for (int i=1;i<=m;i++) { int x=read(),y=read(),z=read(); push(x,y,(long long)z); push(y,x,(long long)z); } spfa(S); dfs1(S); //求最短路图 memset(head,0,sizeof(head)),tot=0; topsort(); dfs2(S); //建支配树 printf("%d\n",ans); return 0;}
阅读全文
0 0
- codeforces 757F Team Rocket Rises Again(最短路+支配树)
- Codecraft-17 and Codeforces Round #391 F - Team Rocket Rises Again (支配树)
- BJ模拟 Team Rocket Rises Again(支配树DominatorTree + Lengauer-Tarjan)
- codeforces 601 A. The Two Routes (最短路d+f)
- 【最短路】NEERC15 F Froggy Ford (Codeforces GYM 100851)
- Codeforces-786B-Legacy (线段树+最短路)
- Codeforces 707B Bakery(最短路)
- Gym 100917F Find the Length(最短路+生成树)
- HDU4251-The Famous ICPC Team Again(划分树)
- hdu 4251 The Famous ICPC Team Again(划分树)
- HDU 4251 The Famous ICPC Team Again (划分树)
- HDU4251 The Famous ICPC Team Again (主席树)
- HDU4251 The Famous ICPC Team Again(划分树裸)
- HDU 2544(2013.9.21周赛F题:最短路)
- 暑假-最短路(Bellman-ford、spfa)-F - Wormholes
- HDU_4251_The Famous ICPC Team Again(划分树)
- codeforces 601A (最短路)
- CodeForces 689B【最短路】
- ijkplayer编译
- 点到线段的最短距离算法(转自 http://blog.sina.com.cn/s/blog_5d5c80840101bnhw.html)
- 深入理解javascript原型和闭包(完结)
- notepad++ 如何修改已经添加的命令
- ios图片编辑(看这个就够了!)
- codeforces 757F Team Rocket Rises Again(最短路+支配树)
- python-------------自定义str转换成int的函数
- 数据结构实验之查找二:平衡二叉树
- 面向对象
- 移动端适配
- Jemter定时器 介绍和作用
- java除法,保留多位小数
- 小程序时间 yyyy-MM格式实现
- Caffe for Python 官方教程(翻译)