最短路

来源:互联网 发布:教师网络培训服务平台 编辑:程序博客网 时间:2024/06/05 19:35

题意:
N 个结点、M 个含K 个结点的完全子图构成一个奇怪的图,问从结点1走到结点N 最少需要经过多少个结点。

N100,000 ; K,M1000

分析:
对于每个点,我们可记录包含它的子图序号,然后bfs,加入广搜队列的是子图的序号,显然每个子图只会入队一次。用队列头子图中的所有点来搜索其他子图。

#include <cstdio>#include <algorithm>#include <cstring>using namespace std;const int N = 1e3 + 10;int d[N * 100],G[N * 100],next[N * N],to[N * N];struct gp {    int s[N];} g[N];int n,m,k,l[2],r[2],tot;int a[2][N],p[N];void add(int x,int y) {    to[++ tot] = y;    next[tot] = G[x];    G[x] = tot;}int main() {    scanf("%d%d%d",&n,&k,&m);    for (int i = 1;i <= m;i ++) {        for (int j = 1;j <= k;j ++) {            scanf("%d",&g[i].s[j]);            add(g[i].s[j],i);            if (g[i].s[j] == 1) a[0][++ r[0]] = i,p[i] = true;        }    }    memset(d,1,sizeof(d));    int Inf = d[1],q = 0,dis = 1;    d[1] = 1;    while (r[q]) {        dis ++;        while (l[q] < r[q]) {            int x = a[q][++ l[q]];            for (int i = 1;i <= k;i ++) {                int cur = g[x].s[i];                if (d[cur] != Inf) continue;                d[cur] = dis;                for (int j = G[g[x].s[i]];j;j = next[j]) {                    if (p[to[j]]) continue;                    p[to[j]] = true;                    a[1 - q][++ r[1 - q]] = to[j];                }            }        }        l[q] = r[q] = 0;        q = 1 - q;        if (d[n] != Inf) break;    }    if (d[n] == Inf) printf("-1");else printf("%d",d[n]);}
0 0
原创粉丝点击