NOIp 2014 寻找道路【图的遍历/最短路】By cellur925

题目传送门

比较裸的图论,结果自己还是没做出来,我真菜。

我们根据题意,只要把不能通向终点的点求出,然后再分别以这些点为起点,求出它们能到达的点,这些点也不能在路径上。

之后跑一个最短路即可。

 

注意以上操作均是在建反图的基础上进行的。我们交换起终点,这是等价的。

 

细节操作:开新数组记录不能到达的点,因为搜索还没结束,会重复。

 

Code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<queue>
 4 
 5 using namespace std;
 6 const int inf=0x3f3f3f3f;
 7 
 8 int n,m,x,y,s,t,tot,qwq;
 9 int head[10090],vis[10090],laz1[10090],dis[10090],tmp[10090],laz[10090];
10 struct node{
11     int to,next;
12 }edge[200090];
13 
14 void add(int x,int y)
15 {
16     edge[++tot].to=y;
17     edge[tot].next=head[x];
18     head[x]=tot;
19 }
20 void dfs(int x)
21 {
22     laz1[x]=1;
23     for(int i=head[x];i;i=edge[i].next)
24     {
25         int y=edge[i].to;
26         if(laz1[y]) continue;
27         dfs(y); 
28     }
29 }
30 
31 void spfa()
32 {
33     queue<int>q;
34     for(int i=1;i<=n;i++) dis[i]=inf;
35     q.push(t);vis[t]=1;dis[t]=0;
36     while(!q.empty())
37     {
38         int x=q.front();q.pop();vis[x]=0;
39         if(!laz[x]) continue;
40         for(int i=head[x];i;i=edge[i].next)
41         {
42             int y=edge[i].to;
43             if(dis[y]>dis[x]+1&&laz[y])
44             {
45                 dis[y]=dis[x]+1;
46                 if(!vis[y]) q.push(y),vis[y]=1; 
47             } 
48         }
49     }
50 }
51 
52 int main()
53 {
54     scanf("%d%d",&n,&m);
55     for(int i=1;i<=m;i++)
56         scanf("%d%d",&x,&y),add(y,x);
57     scanf("%d%d",&s,&t);
58     dfs(t);
59     if(!laz1[s])
60     {
61         printf("-1");
62         return 0;
63     }
64     for(int i=1;i<=n;i++)
65     {
66         if(!laz1[i])
67         {
68             for(int k=head[i];k;k=edge[k].next)
69                 tmp[++qwq]=edge[k].to;
70         }
71         else laz[i]=1;
72     }
73     for(int i=1;i<=qwq;i++) laz[tmp[i]]=0;
74     spfa();
75     printf("%d",dis[s]);
76     return 0;
77 } 
View Code

 

转载于:https://www.cnblogs.com/nopartyfoucaodong/p/9544123.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值