[BZOJ3832][Poi2014]Rally(拓扑序+线段树)
来源:互联网 发布:淘宝哪个店有原味丝袜 编辑:程序博客网 时间:2024/06/18 16:06
题目描述
传送门
题解
考场上只会打枚举删点的暴力,学长讲题了 之后感觉很厉害呀。
设f[i],g[i]分别表示到点i的最长路径和从点i开始的最长路径.通过两遍拓扑排序就可以求出这两个数组.
对于一条边(u,v)它可以产生的最长路径就是f[u]+e[i].v+g[v];
我们用权值线段树维护当前所有合法边产生的最长路径的最大值.考试的时候一直在往枚举的方向考虑,没有想到动态维护直接查询可以用到权值线段树.
首先把g[i]数组加入线段树.
按拓扑序依次枚举每一个点x.
把指向它的边产生的最长路径和g[x]从线段树中删除.
当前全局最大值就是删掉这个点的最长路径.
然后把这个点连出去的边产生的最长路径和f[x]加入线段树
时间复杂度O(nlog(n))
代码
#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<queue>using namespace std;const int N=5e5+5;const int M=1e6+5;const int INF=2e9;int n,m,cnt,Max,ans=INF,ansp;int tot,point[N],v[M],nxt[M];int tot1,point1[N],v1[M],nxt1[M];int f[N],g[N],topo[N],du[N];bool vis[N];struct hp{int x,y;}edge[M];struct hq{int pt,step;};int sum[(N+1)*4];queue <hq> q;inline void addedge(int x,int y){ ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}inline void add(int x,int y){ ++tot1; nxt1[tot1]=point1[x]; point1[x]=tot1; v1[tot1]=y;}inline void Topo(int *a){ for (int i=1;i<=n;++i) if (!du[i]) { q.push((hq){i,0}); vis[i]=true; } while (!q.empty()) { hq now=q.front(); q.pop(); topo[++cnt]=now.pt; a[now.pt]=now.step; for (int i=point[now.pt];i;i=nxt[i]) if (!vis[v[i]]) { du[v[i]]--; if (!du[v[i]]) { vis[v[i]]=true; q.push((hq){v[i],now.step+1}); } } }}inline void update(int now){ sum[now]=sum[now<<1]+sum[now<<1|1];}inline void point_change(int now,int l,int r,int x,int v){ int mid=(l+r)>>1; if (l==r) { sum[now]+=v; return; } if (x<=mid) point_change(now<<1,l,mid,x,v); else point_change(now<<1|1,mid+1,r,x,v); update(now);}inline int query(int now,int l,int r){ int mid=(l+r)>>1; if (l==r) return l; if (sum[now<<1|1]) return query(now<<1|1,mid+1,r); else if (sum[now<<1]) return query(now<<1,l,mid); else return 0;}int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=m;++i) { scanf("%d%d",&edge[i].x,&edge[i].y); addedge(edge[i].y,edge[i].x); du[edge[i].x]++; } Topo(g); tot=0; memset(point,0,sizeof(point)); memset(nxt,0,sizeof(nxt)); memset(v,0,sizeof(v)); memset(du,0,sizeof(du)); memset(vis,0,sizeof(vis)); cnt=0; for (int i=1;i<=m;++i) { addedge(edge[i].x,edge[i].y); add(edge[i].y,edge[i].x); du[edge[i].y]++; } Topo(f); for (int i=1;i<=n;++i) point_change(1,1,n,1+g[i],1); for (int i=1;i<=n;++i) { int now=topo[i]; for (int i=point1[now];i;i=nxt1[i]) point_change(1,1,n,1+g[now]+f[v1[i]]+1,-1); point_change(1,1,n,1+g[now],-1); Max=query(1,1,n)-1; if (Max<ans) { ans=Max; ansp=now; } for (int i=point[now];i;i=nxt[i]) point_change(1,1,n,1+f[now]+g[v[i]]+1,1); point_change(1,1,n,1+f[now],1); } printf("%d %d\n",ansp,ans);}
0 0
- [BZOJ3832][Poi2014]Rally(拓扑序+线段树)
- 【bzoj3832】【poi2014】【Rally】【拓扑排序+线段树】
- 【POI2014】Rally(拓扑序+线段树)
- BZOJ3832: [Poi2014]Rally 拓扑排序
- bzoj 3832: [Poi2014]Rally(线段树+拓扑排序)
- BZOJ3832: [Poi2014]Rally
- BZOJ3832[Poi2014] Rally
- BZOJ3832: [Poi2014]Rally
- BZOJ3832: [Poi2014]Rally
- bzoj 3832: [Poi2014]Rally 线段树+拓扑排序
- 【bzoj 3832】 [Poi2014] Rally (权值线段树+拓扑排序)
- BZOJ 3832 Poi2014 Rally 拓扑排序+堆
- BZOJ 3832 [Poi2014] Rally 拓扑排序
- BZOJ 3832: [Poi2014]Rally拓扑排序
- 【bzoj 3832】: [Poi2014]Rally
- bzoj 3832: [Poi2014]Rally
- BZOJ 3832 [Poi2014]Rally
- POI20143832: [Poi2014]Rally
- java学习之路 之 高级类特性1-面向对象特征之二:继承及方法重写(override)
- 多文件开发 按位运算符 预处理指令 进制等
- Docker 1.12 Swarm 模式剖析
- 随机数安全那些事儿
- Hive 报错 java.lang.NoSuchMethodError: org.apache.hadoop.hive.ql.ppd.ExprWalkerInfo.getConvertedNode
- [BZOJ3832][Poi2014]Rally(拓扑序+线段树)
- 大型网站系统架构的演化
- 20160802
- Think In Java 笔记1 initialization & Cleanup
- Spark Streaming + Kafka direct 从Zookeeper中恢复offset
- linux-TCP网络接口传输速率测试程序
- Mysql的批量操作
- 装系统之ThinkpadE450
- 2016多校训练Contest5: 1005 Interesting hdu5785