1. 程式人生 > >【SDOI2009】Elaxia的路線(拓撲+最短路+dp)

【SDOI2009】Elaxia的路線(拓撲+最短路+dp)

先找出Elaxia的最短路 重新建圖 在此圖上我們再標記同時也是w**的最短路的邊

顯然這是一個DAG 可以做dp 設f[i]表示以i點結尾的最長公共連續和(公共路徑一定是一條鏈) 則f[vis]=max(f[now],f[now]+e[u].val*e[u].flag)(flag表示是否也是w**的最短路)

為了使得沒有後效性 需要在拓撲排序時做dp

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string> 
#include<algorithm>
#include<queue>
#define N 1505
#define INF 0x3f3f3f3f
using namespace std;
template <class T>
inline void read(T &x)
{
    x=0;
    static char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
}
int n,m,x1,y1,x2,y2;
struct Edge
{
    int from,to,next,val,flag;
}edge[N*N],res[N*N];
int tot,first[N],cnt,head[N];
inline void addedge(int x,int y,int z)
{
    tot++;
    edge[tot].from=x; edge[tot].to=y; edge[tot].next=first[x]; edge[tot].val=z; first[x]=tot;  
}
inline void Rebuild_Graph(int x,int y,int z)
{
    cnt++;
    res[cnt].from=x; res[cnt].to=y; res[cnt].next=head[x]; res[cnt].val=z; head[x]=cnt;  
}
int dis[N][5];
bool visit[N];
typedef pair<int,int> Pair;
void dijkstra(int s,int f)
{
     memset(visit,false,sizeof(visit));
     priority_queue<Pair,vector<Pair>,greater<Pair> > heap;
     heap.push(make_pair(0,s)); dis[s][f]=0;
     while(!heap.empty())
     {
        int now=heap.top().second;
        heap.pop();
        if(visit[now])  continue;
        visit[now]=true;
        for(int u=first[now];u;u=edge[u].next)
        {
            int vis=edge[u].to;
            if(dis[now][f]+edge[u].val<dis[vis][f])
            {
                dis[vis][f]=dis[now][f]+edge[u].val;
                heap.push(make_pair(dis[vis][f],vis));
            }
        }
     }
}
int in[N];
void rebuild()
{
    for(int u=1;u<=tot;u++)
    {
        int x=edge[u].from; int y=edge[u].to;
        if(dis[x][1]+edge[u].val+dis[y][2]==dis[y1][1])
        {
            Rebuild_Graph(x,y,edge[u].val); //重新建圖(Elaxia的最短路)
            if(dis[x][3]+edge[u].val+dis[y][4]==dis[y2][3]||dis[x][4]+edge[u].val+dis[y][3]==dis[y2][3])
                res[cnt].flag=1;
            in[y]++;
        }
    }
}
int f[N];
void Topo_sort()
{
    queue <int> q;
    q.push(x1);
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        for(int u=head[now];u;u=res[u].next)
        {
            int vis=res[u].to;
            in[vis]--;  
            f[vis]=max(f[vis],f[now]+res[u].val*res[u].flag);
            if(!in[vis]) q.push(vis);   
        }
    }
}
int main()
{
    read(n),read(m);
    read(x1),read(y1),read(x2),read(y2);
    for(int i=1,x,y,z;i<=m;i++)
    {
        read(x),read(y),read(z);
        addedge(x,y,z); addedge(y,x,z);
    }   
    memset(dis,0x3f,sizeof(dis));
    dijkstra(x1,1); dijkstra(y1,2); dijkstra(x2,3); dijkstra(y2,4);
    rebuild(); Topo_sort();
    cout<<f[y1];
    return 0;
}