POJ - 3160 Father Christmas flymouse DAG最长路
又來做這一道縮點的裸題,發現圖轉化為DAG后明顯是一個最長路,那么有沒有固定都求法呢,查詢資料后發現的確是一種固定的做法。
DAG最長路,分為兩種固定終點和不固定終點。
令dp[i]表示從i頂點出發能獲得的最長路徑長度,這樣所有的d[i]的最大值就是整個DAG的最長路徑長度。
注意到dp[i]表示從i頂點出發能獲得的最長路徑長度,如果從i號頂點出發能直接到達頂點j1,j2..jk,而dp[j1]..dp[jk]均已知。那么就有
????????????????????????????dp[i]=max{dp[j]+length[i->j](i,j)∈E}?
顯然,根據上面的思路需要按照逆拓撲排序來求解dp數組(因為最后的頂點沒有出邊),但有木有辦法不求逆拓撲排序也能計算dp數組呢?當然有,那就是遞歸。其基于鄰接矩陣實現的代碼如下:
1.不固定終點,初始值設為0,就如同該題,此時權值是以點的形式。
memset(dp,0,sizeof(dp));
int DP(int u)
{if(dp[u]!=-1)return dp[u];dp[u]=sum[u];for(int i=0;i<v[u].size();i++){int e=v[u][i];dp[u]=max(dp[u],DP[e]+sum[u]);}return dp[u];
}
2:固定終點,求DAG的最長路徑,有了上面的經驗,應當能很容易想到這個問題延伸問題的解決方案。假設規定的終點為T。那么可以令dp[i]表示從i號頂點出發到達終點T能獲得的最長路徑長度。,如果從i號頂點出發能直接到達頂點j1,j2..jk,而dp[j1]..dp[jk]均已知,那么就有dp[i]=max{dp[j]+length[i->j](i,j)∈E} 。可以發現怎么和問題(1)的式子是一樣的。如果僅僅是這樣就無法體現出dp數組的含義中添加的“到達終點T的描述”。
那么這兩個問題的區別在哪呢?沒錯,邊界。在第一個問題中沒有固定的終點,因此所有出度為0的頂點dp值為0是邊界;但在這個問題中固定了終點,因此邊界應當為dp[T]=0。那么還能像之前那樣對整個dp數組初始化為0?不行,此處會有個問題,由于從某頂點出發可能無法到達終點T(例如出度為0的頂點),因此按照之前的做法出度為0的頂點到T的最長路徑長度為0,這顯然是不符合邏輯的。合適的做法是初始化dp數組為一個負的大數,來保證“”無法到達終點”的含義得以表達(即-Inf,消除其他出度為0的頂點對前驅結點的最長距離的干擾); 代碼如下:此時權值是以邊的形式。
int DP(int u)
{if(dp[u]!=-inff) return dp[u];for(int i=0;i<v[u].size();i++){int e=v[u][i];dp[u]=max(dp[u],DP[e]+len[u][e]);}return dp[u];
}
AC代碼:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#define myself i,l,r
#define lson i<<1
#define rson i<<1|1
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define inff 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define PI 3.14159265358979323846
#define me(a,b) memset(a,b,sizeof(a))
#define min4(a,b,c,d) min(min(a,b),min(c,d))
#define min3(x,y,z) min(min(x,y),min(y,z))
const int dir[4][2]= {0,-1,-1,0,0,1,1,0};
typedef long long ll;
const ll inFF=9223372036854775807;
typedef unsigned long long ull;
using namespace std;
const int maxn=3e4+5;
const int maxm=150005;
int Stack[maxn],inStack[maxn],low[maxn],head[maxn],dfn[maxn],val[maxn],belong[maxn],sum[maxn],dp[maxn];
int sign,cnt,top,t,m,n;
vector<int>v[maxn];
struct node
{int to,p;
}edge[maxm];
void init()
{sign=cnt=t=top=0;for(int i=0;i<=n;i++){v[i].clear();inStack[i]=sum[i]=dfn[i]=low[i]=0;head[i]=dp[i]=-1;}
}
int DP(int u)
{if(dp[u]!=-1)return dp[u];dp[u]=sum[u];for(int i=0;i<v[u].size();i++){int e=v[u][i];dp[u]=max(dp[u],dp[e]+dp[u]);}return dp[u];
}
void add(int u,int v)
{edge[sign]=node{v,head[u]};head[u]=sign++;
}
void tanjar(int u)
{low[u]=dfn[u]=++t;Stack[++top]=u;inStack[u]=1;for(int i=head[u];i!=-1;i=edge[i].p){int e=edge[i].to;if(!dfn[e]) tanjar(e),low[u]=min(low[u],low[e]);else if(inStack[e]) low[u]=min(low[u],dfn[e]);}int x;if(low[u]==dfn[u]){cnt++;do{x=Stack[top--];inStack[x]=0;sum[cnt]+=val[x];belong[x]=cnt;}while(u!=x);}
}
int main()
{int x,y;while(cin>>n>>m){init();for(int i=0;i<n;i++) scanf("%d",&val[i]),val[i]=(val[i]>=0)?val[i]:0;for(int i=0;i<m;i++) scanf("%d %d",&x,&y),add(x,y);for(int i=0;i<n;i++) if(!dfn[i]) tanjar(i);for(int i=0;i<n;i++){for(int j=head[i];~j;j=edge[j].p){int e=edge[j].to;if(belong[i]!=belong[e])v[belong[i]].push_back(belong[e]);}}int ans=0;for(int i=1;i<=cnt;i++) ans=max(ans,DP(i));cout<<ans<<endl;}return 0;
}
?
總結
以上是生活随笔為你收集整理的POJ - 3160 Father Christmas flymouse DAG最长路的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: string 基本用法
- 下一篇: HDU 2586 How far awa