P2149 [SDOI2009]Elaxia的路線 題解
阿新 • • 發佈:2021-08-11
Elaxia的路線
求兩對點間的最短路的最長公共路徑。
思路
記錄哪些邊在公共的最短路徑上。做法:跑四遍最短路,判斷是否同時滿足兩個點對disfromS[u]+w[i]+disfromT[v]==disfromS[T]
。摳出公共路徑(有向的,最短路求後),在公共路徑組成的新圖上考慮最長路徑。轉化為套路性問題求最大鏈長,拓撲排序DP即可。
dijstera更快。
程式碼
艱難困苦,玉汝於成int n,m,id; int s1,t1,s2,t2; int h[N],e[M],ne[M],w[M],idx; int h1[N],e1[M],ne1[M],w1[M],idx1; int dis[4][N]; int din[N],f[N]; bool vis[N]; inline void add(int a,int b,int c) {...} inline void add1(int a,int b,int c) {...} inline void spfa(int rt) {...} inline void new_graph() { for(int u = 1;u <= n;u++) for(int i = h[u];~i;i = ne[i]){ int j = e[i]; if((dis[0][u] + w[i] + dis[1][j] == dis[0][t1])){//注意判斷第二個正反兩向邊,第一個必然正反都被遍歷 if(dis[2][u] + w[i] + dis[3][j] == dis[2][t2]) add1(u,j,w[i]); if(dis[2][j] + w[i] + dis[3][u] == dis[2][t2]) add1(j,u,w[i]); } } } inline void topsort() { queue<int> q; memset(f,-INF,sizeof f); for(int i = 1;i <= n;i++){ if(!din[i]){ f[i] = 0; q.push(i); } } while(q.size()) { int u = q.front(); q.pop(); for(int i = h1[u];~i;i = ne1[i]){ int j = e1[i];din[j]--; if(f[j] < f[u] + w1[i]) f[j] = f[u] + w1[i]; if(!din[j]) q.push(j); } } } signed main() { id = 1;spfa(s1); id = 2;spfa(t1); id = 3;spfa(s2); id = 4;spfa(t2); new_graph(); topsort(); int mx = -1; for(int i = 1;i <= n;i++) mx = max(mx,f[i]); printf("%d\n",mx); return 0; }