POJ 3255 Roadblocks

最短路预处理+枚举。

1到n的次短路长度必然等于 从1走到X的最短路+x到y的边权+y到n的最短路。

首先预处理好1到每一个节点的最短路,和n到每一个节点的最短路。

然后枚举每一条边作为中间边[x,y]或者[y,x],如果加起来长度是最短路则跳过,否则更新答案。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

const int INF=0x7FFFFFFF;
const int maxn=5000+10;
struct Edge
{
    int u,v;
    int w;
}e[200000+10];
int n,m;
vector<int>g[maxn];
int dis[2][maxn];
bool flag[maxn];

void init()
{
    for(int i=1;i<=n;i++) g[i].clear();
    for(int i=1;i<=n;i++) dis[0][i]=dis[1][i]=INF;
    dis[0][1]=0; dis[1][n]=0;
}

void read()
{
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        g[e[i].u].push_back(i);
        e[i+m].u=e[i].v; e[i+m].v=e[i].u; e[i+m].w=e[i].w;
        g[e[i+m].u].push_back(i+m);
    }
}

void SPFA(int st)
{
    queue<int>Q; memset(flag,0,sizeof flag);
    int now; if(st==1) now=0; else now=1;
    Q.push(st); flag[st]=1;
    while(!Q.empty())
    {
        int head=Q.front(); Q.pop(); flag[head]=0;
        for(int i=0;i<g[head].size();i++)
        {
            int id=g[head][i];
            int cost=e[id].w,to=e[id].v;
            if(dis[now][head]+cost<dis[now][to])
            {
                dis[now][to]=dis[now][head]+cost;
                if(!flag[to]) {flag[to]=1;Q.push(to);}
            }
        }
    }
}

void work()
{
    int f=dis[0][n];
    int ans=INF;
    for(int i=1;i<=2*m;i++)
    {
        int u=e[i].u, v=e[i].v;
        if(dis[0][u]+e[i].w+dis[1][v]==f) continue;
        ans=min(dis[0][u]+e[i].w+dis[1][v],ans);
    }
    printf("%d\n",ans);
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        init(); read();
        SPFA(1); SPFA(n);
        work();
    }
    return 0;
}

 

posted @ 2016-03-14 09:55  Fighting_Heart  阅读(162)  评论(0编辑  收藏  举报