Bits town walking (Walk) [dotted] + bfs + dfs

Judge Online : NOIP2016 ten even measured first field T3

The Label : the virtual point, bfs, dfs

Title Description

Description / Tips

To 100% of the data, \ (n-<= 200000 \) , \ (m <= 300000 \) , \ (val_i <= 20 is 2 ^ {} \)

answer

Since it is a binary only if \ (val_j \) is \ (val_i \) when a subset of, i even have a side of the j.

1. Let's look at if only the original image, which is not considered twenty-two even how to get each point edge distance away from the source point 1?

Obviously run a shortest path. But because the right side is 1, do not run \ (dijkstra / spfa \) or something, and direct it again \ (O (N) \) The \ (bfs \) on it.

2. Consider twenty-two side even when how to do?

If directly connected twenty-two determines whether edges are \ (O (N ^ 2) \) , can not afford the time and space.

Consider setting the virtual point , i.e. the edge \ (U-> V \) , is converted to \ (U-> val_u -> ...-> val_v-> V \) . Do not mind the direction of the first upper edge. The basic idea is to use the binary number as intermediary to simulate even edge , according to (val_i \) \ data range, at most only \ (2 ^ {20} = 1048576 \) digits, which seem to do the comparison.

Order \ (DIS [] \) represents the distance from each point source 1, since the point corresponding to the virtual media, we are not to be included in the distance, the array size opening \ ((N) \) . The initial \ (DIS [] \) is initialized to -1, the source \ (DIS [. 1] = 0 \) .

Now set \ (bfs \) head of the queue elements \ (the X-\) .

According to the original idea, let \ (x \) twenty-two even when the side can be connected to the real point \ (the y-\) ( \ (val_j∈val_i \) ), if you have not visited \ (the y-\) (ie \ (DIS [Y] == -. 1 \) ) the \ (DIS [Y] = DIS [X] + 1'd \) . Bfs accordance with the process of walking, it should also \ (y \) added to the end of the queue. So how to go to the extent feasible time to simulate it? Direct sets a \ (the DFS \) , to violent enumerate \ (val_x \) subset, of course, if you really do it after each removal team first, time complexity is \ (O (number of sub-sets of val_x) \) , will be T. Back to just take \ (bfs \) to search the shortest lines, if a point is first accessed, then the current distance is ready to update his shortest path to the source, so the direct memory of it, only when the current binary number is not \ (mark \) only continue dfs subset.

So that each binary number will be up to get one. The total time complexity is approximately \ (O (2 ^ {} + 20 is N + M) \) .

The complete code is as follows:

ps: The following code by the \ (E \) between the deposit and the solid dots solid dot original directed edges , with \ (G \) deposit \ (val_i \) points \ (I \) directed edge.

#include<bits/stdc++.h>
using namespace std;
const int N=200010,M=300010;
inline int read(){
    int x=0;char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x;
}
struct Edge{
    int to,nxt;
}e[M];//实点与实点 
vector<int>g[1<<20];//虚点连向实点 
int n,m,head[N],cnt;
inline void link(int u,int v){
    e[++cnt].to=v,e[cnt].nxt=head[u];
    head[u]=cnt;
}

queue<int>q;
int val[N],dis[N],mark[1<<20];
void boom(int now,int s,int lst){//解决子集 
    if(mark[now])return;
    mark[now]=1;
    for(int i=0;i<g[now].size();i++){
        int y=g[now][i];
        if(dis[y]==-1){
            dis[y]=dis[s]+1;
            q.push(y);
        }
    }
    for(int i=lst+1;i<=20;i++)if((1<<i)&now)boom(now^(1<<i),s,lst+1);       
}
void bfs(){
    memset(dis,-1,sizeof(dis));
    q.push(1);dis[1]=0;
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=head[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(dis[y]==-1){
                dis[y]=dis[x]+1;
                q.push(y);
            }
        }
        boom(val[x],x,-1);
    }
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++){
        val[i]=read();
        g[val[i]].push_back(i);
    }
    for(int i=1;i<=m;i++){
        int u=read(),v=read();
        link(u,v);
    }
    bfs();
    for(int i=1;i<=n;i++)printf("%d\n",dis[i]);
} 

Guess you like

Origin www.cnblogs.com/Tieechal/p/11545479.html