GalaxyOJ-1000 (punto de contracción + camino más corto)

tema

http://www.gdfzoj.com/oj/contest/247/problems/3
tema
rango de datos

análisis

  • Para los primeros cuatro datos, el mapeo directo de fuerza bruta y SPFA es el camino más corto.
  • Analice, para los siguientes datos, es principalmente el "borde especial" (es decir, el borde obtenido de la operación AND) que necesita ser cuadrado al construir el mapa. Puede optimizar esto aquí.
  • Se puede considerar que después de terminar des [] de un punto, se actualizan directamente todos los puntos que puede alcanzar a través del "borde especial".
  • Dado que la longitud del lado es 1, para cada punto, el valor de la primera actualización debe ser el más pequeño. Obtenga el vector "rango de peso de punto" y guarde el peso de punto como su número de punto. Cada vez que lo discuta, dfs Se puede actualizar en un solo paso. (No es necesario cambiar los que se han actualizado antes)

programa

#include <cstdio>
#include <cstring>
#include <vector>
#define Add(x,y) (to[++num]=head[x],head[x]=num,V[num]=y)
#define For(x) for(int h=head[x],o=V[h]; h; o=V[h=to[h]])
using namespace std;
int head[200005],to[300005],V[300005],num;
int q[2000000],vis[200005],f[1100000],l,r;
int n,m,val[200005],dis[200005];
vector <int> a[1100000];

void dfs(int x,int ds){     //从某个 权值为 x 的点 通过特殊路到的点,dis=ds 
    if (f[x]) return;
    f[x]=1;
    for (int i=20; i>=0; i--) if (x&(1<<i)) dfs(x^(1<<i),ds);
    if (!a[x].empty()) for (int i=0; i<a[x].size(); i++){
        int o=a[x][i];
        if (vis[o]) continue;
        vis[o]=1;
        dis[o]=ds;
        q[++r]=o;
    }
}

int main(){
    freopen("1.txt","r",stdin);
    scanf("%d%d",&n,&m);
    for (int i=1; i<=n; i++) scanf("%d",val+i),a[val[i]].push_back(i);
    for (int i=1,x,y; i<=m; i++) scanf("%d%d",&x,&y),Add(x,y);  
    memset(dis,0x7f,sizeof(dis)); dis[1]=0;
    for (q[l=r=0]=vis[1]=1; l<=r; l++){
        int u=q[l];
        For(u) if (!vis[o]){
            vis[o]=1;
            dis[o]=dis[u]+1;
            q[++r]=o;
        }
        dfs(val[u],dis[u]+1);       //讨论一下 u 能连到的特殊路 
    }
    for (int i=1; i<=n; i++)
        printf("%d\n",dis[i]>n?-1:dis[i]);
}

Supongo que te gusta

Origin blog.csdn.net/jackypigpig/article/details/78470602
Recomendado
Clasificación