BZOJ 2200: [Usaco2011 Jan]道路和航线

35 篇文章 0 订阅
16 篇文章 1 订阅

这道题嘛 其实好像直接上spfa就好了 不过他有意想卡你一下

不过我加了一个优化就过了(原来spfa有优化。。SLF就好 LLL好像不常用)

dijkstra的做法的确快很多 不过也麻烦的多了(不过应该是思维性所在吧)

不难发现 根据题意 因为不存在走回来的情况 负边连接的都是两个连通块

所以分开来对每个连通块内做dijkstra 然后外面对于连通块用拓扑序来搞 搞连通块的时候把外面进来的扔进队列就好。。细节很多

想想就觉得热爱学习也是蛋疼打了两种做法 第二种真是烦。。要注意细节啊。。

是不是应该夸我(手动笑cry)

spfa:

#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;
const int N=25010,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,next,c;}a[N*6]; int len,first[N];
void ins(int x,int y,int c)
{
    a[++len].y=y,a[len].c=c,a[len].next=first[x],first[x]=len;
}
bool v[N]; int d[N];
deque<int>q;
int main()
{
    int i,j,x,y,c,n,m1,m2,st;
    n=read(),m1=read(),m2=read(),st=read();
    for(i=1;i<=m1;i++)
    {
        x=read(),y=read(),c=read();
        ins(x,y,c),ins(y,x,c);
    }
    for(i=1;i<=m2;i++)
        x=read(),y=read(),c=read(),ins(x,y,c);
    q.push_front(st); me(d,63);
    int s=0,l=1; d[st]=0,v[st]=1;
    while(!q.empty())
    {
        x=q.front();
        q.pop_front(); v[x]=0;
        for(int k=first[x];k;k=a[k].next)
        {
            y=a[k].y;
            if(d[y]>d[x]+a[k].c)
            {
                d[y]=d[x]+a[k].c;
                if(v[y])continue;
                v[y]=1;
                if(!q.empty())
                {
                    if(d[y]<d[q.front()])q.push_front(y);
                    else q.push_back(y);
                }
                else q.push_back(y);
            }
        }
    }
    for(i=1;i<=n;i++)
        if(d[i]>inf)printf("NO PATH\n");
        else printf("%d\n",d[i]);
    return 0;
}



dijkstra:

#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=25010,inf=1e9;
inline int read()
{
    LL 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 x,y,next,c;}a[N*6]; int len,first[N];
void ins(int x,int y,int c)
{
    a[++len].y=y,a[len].c=c,a[len].next=first[x],first[x]=len;
}
struct P{
    int x,y;
    bool operator <(const P &t) const
    {
        return y>t.y;
    }
};
bool v[N]; int d[N],fa[N],p[N],l,r[N];
priority_queue<P>q;
vector<int>u[N],J[N];
queue<int>Q;
int fi(int x){return fa[x]==x?x:fa[x]=fi(fa[x]);}
int main()
{
    int i,j,x,y,c,n,m1,m2,st;
    n=read(),m1=read(),m2=read(),st=read();
    for(i=1;i<=n;i++)fa[i]=i;
    for(i=1;i<=m1;i++)
    {
        x=read(),y=read(),c=read();
        ins(x,y,c),ins(y,x,c),fa[fi(x)]=fi(y);
    }
    l=0; for(i=1;i<=n;i++)if(fa[i]==i)p[i]=++l;
    for(i=1;i<=n;i++)fa[i]=fi(fa[i]);
    for(i=1;i<=m2;i++)
    {
        x=read(),y=read(),c=read();
        a[len+i].x=x,a[len+i].y=y,a[len+i].c=c;
        u[p[fa[x]]].push_back(i+len),r[p[fa[y]]]++;
        J[p[fa[y]]].push_back(y);
    }
    for(i=1;i<=l;i++) if(!r[i])Q.push(i);
    for(i=1;i<=n;i++) if(fa[i]==i&&r[p[i]]==0) J[p[i]].push_back(i);
    me(d,63); d[st]=0; J[p[fa[st]]].push_back(st);
    while(!Q.empty())
    {
        int now=Q.front(); Q.pop();
        for(i=0;i<J[now].size();i++)
        {
            int U=J[now][i];
            q.push( (P){d[U],U} );
        }
        while(!q.empty())
        {
            P g=q.top(); q.pop();
            if(d[g.y]<g.x)continue;
            for(i=first[g.y];i;i=a[i].next)
            {
                y=a[i].y;
                if(d[y]>d[g.y]+a[i].c)
                {
                    d[y]=d[g.y]+a[i].c;
                    q.push( (P){d[y],y} );
                }
            }
        }
        for(i=0;i<u[now].size();i++)
        {
            j=u[now][i]; r[p[fa[a[j].y]]]--;
            if(!r[p[fa[a[j].y]]]) Q.push(p[fa[a[j].y]]);
            d[a[j].y]=min(d[a[j].y],d[a[j].x]+a[j].c);
        }
    }
    for(i=1;i<=n;i++)
        if(d[i]<inf)printf("%d\n",d[i]);
        else printf("NO PATH\n");
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值