寻找道路

http://icpc.upc.edu.cn/problem.php?cid=1687&pid=4

已知只有所有出边都直接或间接指向终点的点才可能被选择,所以就建反边,从终点想起点扫,dfs,bfs均可,在把所有终点不能达到的点打上标记,这些点均不可备选择,并且在反边图中这些点所指向的点也不能被选择(因为在正边图中这些点指向标记点)。因此可以删去图中不符合要求的点,然后跑最短路即可。

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct str
{
    int t,n;
} e[3000010];
struct str1
{
    int t,n;
} e1[3000010];
int n,m,t,tt,i,j,k,s,c[2000005],vv[3000000],t1,can[2000005],S,T
,h[3000005],b[3000005],h1[3000005],v[2000005];
void add(int u,int v)
{
    t++;
    e[t].t=v;
    e[t].n=h[u];
    h[u]=t;
}
void add1(int u,int v)
{
    tt++;
    e1[tt].t=v;
    e1[tt].n=h1[u];
    h1[u]=tt;
}
void bfs(int x)
{
    queue<int>q;
    q.push(x);
    v[x]=1;
    while (q.size())
    {
        int k=q.front();
        q.pop();
        for (int i=h1[k]; i; i=e1[i].n)
        {
            int kk=e1[i].t;
            if (v[kk]==0)
            {
                q.push(kk);
                v[kk]=1;
            }
        }
    }
}
void spfa()
{
    queue<int>q;
    b[S]=0;
    q.push(S);
    while(q.size())
    {
        int k=q.front();
        q.pop();
        for(int i=h[k]; i; i=e[i].n)
        {
            int kk=e[i].t;
            if(!v[kk]||vv[kk]==1)
                continue;
            if(b[kk]>b[k]+1)
            {
                b[kk]=b[k]+1;
                q.push(kk);
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(i=1; i<=m; i++)
    {
        scanf("%d%d",&s,&t1);
        if(s!=t1)
        {
            add(s,t1);
            add1(t1,s);
        }
    }
    scanf("%d%d",&S,&T);
    bfs(T);
    for (i=1; i<=n; i++)
        if (v[i]==0)
            for (j=h1[i]; j; j=e1[j].n)
                vv[e1[j].t]=1;
    for (i=1; i<=n; i++)
        b[i]=1000000000;
    spfa();
    if(b[T]>=1000000000)
        printf("-1\n");
    else
        printf("%d\n",b[T]);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值