JZOJ4858. 【GDOI2017模拟11.4】Walk
2016-11-04 16:15
323 查看
题目描述
在比特镇一共有n 个街区,编号依次为1 到n,它们之间通过若干条单向道路连接。比特镇的交通系统极具特色,除了m 条单向道路之外,每个街区还有一个编码vali,不同街区可能
拥有相同的编码。如果val_i and val_j = val_j,即val_i 在二进制下与val_j 做与运算等于val_j,那么也会
存在一条额外的从i 出发到j 的单向道路。
Byteasar 现在位于1 号街区,他想知道通过这些道路到达每一个街区最少需要多少时间。因为比特
镇的交通十分发达,你可以认为通过每条道路都只需要1 单位时间。
n<=200000,m<=300000,val_i<=220
分析
首先可以发现,边权只有1,那么直接bfs不用最短路。怎么处理额外路径呢?暴力连边是n2的,然而我们发现,假设已经处理了点i的最短路,那么所有没有处理过的,满足and条件的点j都会被处理出来嘛。那么满足and条件的点就是满足在二进制下a[j]是a[i]删掉一些1的结果。同时我们又注意到,相同的a[j]处理一次就够了,如何避免a[j]被处理多次呢?
构建虚拟点,编号n+1~n+max(val_i),表示当真实点的权值为某个值x时,它的最短路是多少。那么我们把这些点加进图里面,每次走一条边就相当于删掉二进制下某个1,一起跑就行了,强制当真实点进入虚拟点要1的花费,出去则不用。
有一些细节,就是虚点优先跑,因为边权为0嘛。另外,如果边要全部建出来,会爆空间。其实对于虚拟点不用存边,因为你知道删去一个1后会是哪个点,根本不用存边。
代码
#include<cstdio> #include<algorithm> #include<set> using namespace std; #define fo(i,j,k) for(i=j;i<=k;i++) const int N=200005,M=300005,er=1048576; int b[M*4],next[M*4],first[N+er],tt; int dis[N+er],n,m,x,y,a ,i,j,k,l,dur,p,d[N+er],e[N+er],q1,q2,p1,p2,z,t; void cr(int x,int y) { tt++; b[tt]=y; next[tt]=first[x]; first[x]=tt; } void bfs() { fo(i,1,n+er) dis[i]=-1; dis[1]=0; d[1]=1; q1=0; q2=1; while (q1<q2) { x=d[++q1]; for(p=first[x];p;p=next[p]) if (dis[b[p]]==-1) { dis[b[p]]=dis[x]+1; d[++q2]=b[p]; } if (dis[a[x]+n]==-1) { dis[a[x]+n]=dis[x]+1; e[1]=a[x]+n; p1=0; p2=1; while (p1<p2) { z=y=e[++p1]; z-=n; for(p=first[y];p;p=next[p]) if (dis[b[p]]==-1) { dis[b[p]]=dis[x]+1; d[++q2]=b[p]; } while (z) { t=y-((z)&(-z)); if (t==n) break; if (dis[t]==-1) { dis[t]=dis[x]+1; e[++p2]=t; } z-=z&(-z); } } } } } int main() { freopen("walk.in","r",stdin); freopen("walk.out","w",stdout); scanf("%d%d",&n,&m); fo(i,1,n) { scanf("%d",a+i); cr(a[i]+n,i); } fo(i,1,m) { scanf("%d%d",&x,&y); cr(x,y); } bfs(); fo(i,1,n) { printf("%d\n",dis[i]); } }
相关文章推荐
- 【JZOJ4858】【GDOI2017模拟11.4】Walk
- 【GDOI2017模拟11.4】Walk
- JZOJ4857. 【GDOI2017模拟11.4】Tourist Attractions
- JZOJ4796 【GDOI2017模拟9.21】三色图 构造可行解
- Day 5 jzoj 4310. 【NOIP2015模拟11.4】最优交换
- 【JZOJ 4314】【NOIP2015模拟11.4】老司机
- 【JZOJ4925】【GDOI2017模拟12.18】稻草人
- 【JZOJ5324】【GDOI2017模拟8.21】麻将堆
- JZOJ4849. 【GDOI2017模拟11.3】记忆的轮廓 期望+答案上界剪枝
- JZOJ4779. 【GDOI2017模拟9.14】鞍点
- [JZOJ4695]【GDOI2017模拟8.14】佐助的难题
- Day 6 jzoj 4312. 【NOIP2015模拟11.4】格点统计
- JZOJ4753【GDOI2017模拟9.4】种树 LCT维护子树信息+换根时维护Dfs序(CC MONOPLOY加强版)
- JZOJ 4863 【GDOI2017模拟11.5】Market
- JZOJ4779 【GDOI2017模拟9.14】鞍点(OICamp 2016 Day 5 T1) 计数问题
- jzoj【GDOI2017第二轮模拟day2】开房间
- 【jzoj4982】【GDOI2017模拟2.23】【加密】【sam】
- JZOJ4800. 【GDOI2017模拟9.24】周末晚会
- [jzoj5073 GDOI2017第二轮模拟] 影魔
- JZOJ4769 【GDOI2017模拟9.9】graph CDQ分治+用按秩合并维护带撤销的并查集(BZOJ 4025)