bzoj1880: [Sdoi2009]Elaxia的路線

題面在這裏

題意:

求一個無向圖中,兩個點對最短路的最長公共路徑。
注意給出的x1,y1和x2,y2不一定是從x走到y,可以是y走到x。

做法:

首先無腦跑最短路QAQ..
事實上,我們要把以x1,y1,x2,y2爲起點的最短路都跑出來。

然後對於一條邊u,v,邊權爲w,假如dis[s-u]+dis[v-t]+w == dis[s-t],則u-v這條邊是在s-t的最短路上的。
我們把同在x1-y1,x2-y2的最短路上的邊取出來重新構圖,在新圖上跑一個拓撲求最長鏈即可。
當然由於可以從y走到x,所以再把x2,y2交換一下再做一次拓撲,取兩次答案的最大值。

代碼:

/*************************************************************
    Problem: bzoj 1880 [Sdoi2009]Elaxia的路線
    User: fengyuan
    Language: C++
    Result: Accepted
    Time: 1148 ms
    Memory: 54796 kb
    Submit_Time: 2018-01-24 17:07:19
*************************************************************/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cctype>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;

inline ll read() {
    char ch = getchar(); ll x = 0; int op = 1;
    for(; !isdigit(ch); ch = getchar()) if(ch == '-') op = -1;
    for(; isdigit(ch); ch = getchar()) x = x*10+ch-'0';
    return x*op;
}
inline void write(ll a) {
    if(a < 0) putchar('-'), a = -a;
    if(a >= 10) write(a/10); putchar('0'+a%10);
}

const int N = 1510;
int n, m, ans, cnt, s1, s2, t1, t2;
int head[N], head2[N], dis[5][N], dp[N], in[N];
bool vis[N];
struct edge {
    int to, nxt, v;
    edge() {}
    edge(int x, int y, int z) { to = x, nxt = y, v = z; }
}e[N*N<<1];

inline void addedge(int x, int y, int z) { e[++ cnt] = edge(y, head[x], z); head[x] = cnt; }
inline void addedge2(int x, int y, int z) { e[++ cnt] = edge(y, head2[x], z); head2[x] = cnt; }
inline void spfa(int p, int s) {
    queue<int> q; q.push(s); dis[p][s] = 0; memset(vis, 0, sizeof vis); vis[s] = 1;
    while(!q.empty()) {
        int u = q.front(); q.pop(); vis[u] = 0;
        for(int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].to;
            if(dis[p][v] > dis[p][u]+e[i].v) {
                dis[p][v] = dis[p][u]+e[i].v;
                if(!vis[v]) { vis[v] = 1; q.push(v); }
            }
        }
    }
}
inline void tp() {
    queue<int> q; memset(dp, 0, sizeof dp);
    for(int i = 1; i <= n; i ++) if(!in[i]) q.push(i);
    while(!q.empty()) {
        int u = q.front(); q.pop(); ans = max(ans, dp[u]);
        for(int i = head2[u]; i; i = e[i].nxt) {
            int v = e[i].to; in[v] --;
            dp[v] = max(dp[v], dp[u]+e[i].v);
            if(!in[v]) q.push(v);
        }
    }
}
int main() {
    n = read(), m = read(), s1 = read(), t1 = read(), s2 = read(), t2 = read();
    for(int i = 1; i <= m; i ++) {
        int x = read(), y = read(), z = read();
        addedge(x, y, z); addedge(y, x, z);
    } memset(dis, 0x3f, sizeof dis);
    spfa(0, s1); spfa(1, t1); spfa(2, s2); spfa(3, t2);
    for(int i = 1; i <= n; i ++)
        for(int j = head[i]; j; j = e[j].nxt) {
            int k = e[j].to;
            if(dis[0][i]+dis[1][k]+e[j].v == dis[0][t1] && dis[2][i]+dis[3][k]+e[j].v == dis[2][t2]) {
                addedge2(i, k, e[j].v); in[k] ++;
            }
        }
    tp();
    swap(dis[2], dis[3]); memset(head2, 0, sizeof head2); memset(in, 0, sizeof in);
    for(int i = 1; i <= n; i ++)
        for(int j = head[i]; j; j = e[j].nxt) {
            int k = e[j].to;
            if(dis[0][i]+dis[1][k]+e[j].v == dis[0][t1] && dis[2][i]+dis[3][k]+e[j].v == dis[2][s2]) {
                addedge2(i, k, e[j].v); in[k] ++;
            }
        }
    tp();
    write(ans); puts("");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章