BZOJ 3538: [Usaco2014 Open]Dueling GPS

35 篇文章 0 订阅
8 篇文章 0 订阅

还是挺不错的

想到从终点反过来跑一次然后标记一下边 最后再正着跑一次最短路就好

#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define me(a,x) memset(a,x,sizeof a)
#define cp(a,x) memcpy(a,x,sizeof a)
using namespace std;
typedef long long LL;
const int N=10010,inf=1e9;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
struct node{int y,c[2],d,next;}a[5*N],b[5*N]; int len,first[2][N];
void ins(int x,int y,int c0,int c1)
{
    b[++len].y=y,b[len].next=first[0][x],first[0][x]=len,b[len].d=2;
    a[len].y=x,a[len].c[0]=c0,a[len].c[1]=c1;
    a[len].next=first[1][y],first[1][y]=len;
}
queue<int>q;
int n,m,d[2][N],l[2][N]; bool v[N];
void spfa(int o)
{
    for(int i=1;i<=n;i++)d[o][i]=inf,v[i]=0;
    d[o][n]=0,v[n]=1;
    q.push(n);
    while(!q.empty())
    {
        int x=q.front(); q.pop(); v[x]=0;
        for(int k=first[1][x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(d[o][y]>d[o][x]+a[k].c[o])
            {
                d[o][y]=d[o][x]+a[k].c[o];
                l[o][y]=k;
                if(!v[y]){v[y]=1; q.push(y);}
            }
        }
    }
}
int f[N];
int main()
{
    int i,j,x,y,c0,c1;
    n=read(),m=read();
    for(i=1;i<=m;i++)
    {
        x=read(),y=read(),c0=read(),c1=read();
        ins(x,y,c0,c1);
    }
    spfa(0),spfa(1);
    for(i=1;i<=n;i++)
    {
        if(l[0][i]) b[l[0][i]].d--;
        if(l[1][i]) b[l[1][i]].d--;
        v[i]=0,f[i]=inf;
    }
    q.push(1); f[1]=0,v[1]=1;
    while(!q.empty())
    {
        x=q.front(),v[x]=0,q.pop();
        for(int k=first[0][x];k;k=b[k].next)
        {
            y=b[k].y;
            if(f[y]>f[x]+b[k].d)
            {
                f[y]=f[x]+b[k].d;
                if(!v[y]){v[y]=1; q.push(y);}
            }
        }
    }
    printf("%d\n",f[n]);
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值