[BZOJ]1880: [Sdoi2009]Elaxia的路线 spfa+拓扑图DP

来源:互联网 发布:加工中心编程实例讲解 编辑:程序博客网 时间:2024/05/21 15:41

Description

最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间。Elaxia和w每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的前提下,一起走的时间尽可能的长。 现在已知的是Elaxia和w**所在的宿舍和实验室的编号以及学校的地图:地图上有N个路 口,M条路,经过每条路都需要一定的时间。 具体地说,就是要求无向图中,两对点间最短路的最长公共路径。

题解:

不错的题目啊!先spfa求出每个点到x1,y1,x2,y2的最短路,然后通过这个判断哪些边同时在两条最短路上,然后做拓扑图DP,搞出最长路就行了。

代码:

#include<bits/stdc++.h>using namespace std;#define LL long longconst int Maxn=1510;const int Maxm=2250010;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<<3)+(x<<1)+ch-'0';ch=getchar();}    return x*f;}int n,m,p[5],f[5][Maxn],de[Maxn];struct Edge{int y,d,next;}e[Maxm],E[Maxm];int last[Maxn],len=0,Last[Maxn],Len=0;void ins(int x,int y,int d){    int t=++len;    e[t].y=y;e[t].d=d;    e[t].next=last[x];last[x]=t;}void Ins(int x,int y,int d){    int t=++Len;    E[t].y=y;E[t].d=d;    E[t].next=Last[x];Last[x]=t;}bool in[Maxn];queue<int>q;void spfa(int o){    f[o][p[o]]=0;    memset(in,false,sizeof(in));    q.push(p[o]);    while(!q.empty())    {        int x=q.front();q.pop();in[x]=false;        for(int i=last[x];i;i=e[i].next)        {            int y=e[i].y;            if(f[o][x]+e[i].d<f[o][y])            {                f[o][y]=f[o][x]+e[i].d;                if(!in[y])in[y]=true,q.push(y);            }        }    }}int F[Maxn],ans=0;void DP(){    memset(F,0,sizeof(F));    for(int i=1;i<=n;i++)    if(!de[i])q.push(i);    while(!q.empty())    {        int x=q.front();q.pop();        for(int i=Last[x];i;i=E[i].next)        {            int y=E[i].y;            de[y]--;if(!de[y])q.push(y);            F[y]=max(F[y],F[x]+E[i].d);        }    }    for(int i=1;i<=n;i++)ans=max(ans,F[i]);}int main(){    n=read();m=read();    for(int i=1;i<=4;i++)p[i]=read();    for(int i=1;i<=m;i++)    {        int x=read(),y=read(),d=read();        ins(x,y,d);ins(y,x,d);    }    memset(f,63,sizeof(f));    for(int i=1;i<=4;i++)spfa(i);    int mn1=2147483647,mn2=2147483647;    for(int i=1;i<=n;i++)mn1=min(mn1,f[1][i]+f[2][i]);    for(int i=1;i<=n;i++)mn2=min(mn2,f[3][i]+f[4][i]);    for(int x=1;x<=n;x++)    {        for(int i=last[x];i;i=e[i].next)        {            int y=e[i].y;            if(f[1][x]+e[i].d+f[2][y]==mn1&&f[3][x]+e[i].d+f[4][y]==mn2)            Ins(x,y,e[i].d),de[y]++;        }    }    DP();    memset(de,0,sizeof(de));    memset(Last,0,sizeof(Last));len=0;    for(int x=1;x<=n;x++)    {        for(int i=last[x];i;i=e[i].next)        {            int y=e[i].y;            if(f[1][x]+e[i].d+f[2][y]==mn1&&f[4][x]+e[i].d+f[3][y]==mn2)            Ins(y,x,e[i].d),de[x]++;        }    }    DP();    printf("%d",ans);}
阅读全文
1 0