NOIP 2014 提高组 Day2 T2 寻找道路

来源:互联网 发布:php就业形势 编辑:程序博客网 时间:2024/05/18 18:18

【题意】给定有向无权图,要求求一条最短路径,使得路径上的每一个点的出边都直接或间接与终点连通

【分析】

除了存本题给出的图外,还要存个逆图,用邻接表存储;

排除不连通的点,就用逆图从t点DFS一次,用used[N]存储连不连通,求出所有的used;

设置数组cant[N],标记每个点能不能取,不能取有两种情况:一是不连通的;二是出边到达不连通的点的点,所以再标记不连通的点的逆图的出边所到达的点;

然后,所有cant[i]=0的点就是可以用的了,再BFS一次求最短路就AC了。

【代码】

#include <cstdio>

#include <cstring>

#include <cstdlib>


using namespace std;


const int N=10001;

const int M=200001;


int n,m,s,t;

struct G

{

int v,next;

}map[M],map1[M];

int tot1,tot,hd1[N],hd[N];

int q[N],l,r=1,level[N];

int used[N],cant[N];


void ins(int u,int v)

{

map[++tot].v=v;

map[tot].next=hd[u];

hd[u]=tot;

}


void ins1(int u,int v)

{

map1[++tot1].v=v;

map1[tot1].next=hd1[u];

hd1[u]=tot1;

}


void init(void)

{

scanf("%d%d",&n,&m);

int x,y;

for (;m--;)

{

scanf("%d%d",&x,&y);

ins(x,y);

ins1(y,x);

}

scanf("%d%d",&s,&t);

}


void DFS(int u)

{

used[u]++;

for (int k=hd1[u];k;k=map1[k].next) if (!used[map1[k].v]) DFS(map1[k].v);

}


void work(void)

{

DFS(t);

for (int i=1;i<=n;i++)

if (!used[i])

{

cant[i]=1;

for (int k=hd1[i];k;k=map1[k].next) cant[map1[k].v]=1;

}

if (cant[s]) {printf("-1\n");return;}

level[q[r]=s]=1;

for (;l^r;)

{

int p=q[++l];

for (int k=hd[p];k;k=map[k].next)

if (!level[map[k].v]&&!cant[map[k].v])

{

if (map[k].v==t) {printf("%d\n",level[p]);return;}

level[map[k].v]=level[p]+1;

q[++r]=map[k].v;

}

}

printf("-1\n");

}


int main(void)

{

init();

work();

return 0;

}

0 0
原创粉丝点击