很顯然這道就是需要先求出強連通分量,然後縮點。縮點之後就是有向無環圖了。實際上這之後,各種方法就都可以了。
已知的dp:1.通過拓撲序用一個隊列來進行dp,圖是原先的圖
2.縮點後建新圖時,將圖反向建。然後對於每一個酒吧,記憶話搜索,到市中心的最短路(我用的這種方法)
spfa:縮點後跑spfa,求出到每一個酒吧的最長路(我不敢確定這樣的複雜度,就沒寫這個)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<stack>
using namespace std;
inline int read()
{
int ans,f=1;char ch;
while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;
ans=ch-'0';
while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';
return ans*f;
}
const int N=600005;
const int inf=0x7777ffff;
int n,m;
int val1[N],val2[N];
int dfn[N],low[N],size,pos[N],id;
int f[N],S,P;
struct aa
{
int to[N*2],pre[N*2],head[N],tot;
void addedge(int x,int y)
{
to[++tot]=y;pre[tot]=head[x];head[x]=tot;
}
}old,now;
void init()
{
n=read();m=read();
int x,y;
for (int i=1;i<=m;i++)
{
x=read();y=read();
old.addedge(x,y);
}
for (int i=1;i<=n;i++) val1[i]=read();
}
stack<int> s;
bool in[N];
void dfs(int u)
{
dfn[u]=low[u]=++id;
s.push(u);
in[u]=true;
for (int i=old.head[u];i;i=old.pre[i])
{
int v=old.to[i];
if (!dfn[v])
{
dfs(v);
low[u]=min(low[u],low[v]);
}
else if (in[v]) low[u]=min(low[u],dfn[v]);
}
if (dfn[u]==low[u])
{
size++;
int v;
do
{
v=s.top();
s.pop();
pos[v]=size;
val2[size]+=val1[v];
in[v]=false;
}while (v!=u);
}
}
void work_graph()
{
for (int u=1;u<=n;u++)
for (int i=old.head[u];i;i=old.pre[i])
{
int v=old.to[i];
if (pos[u]!=pos[v])
now.addedge(pos[v],pos[u]);
}
}
void mx(int u)
{
if (f[u]!=-inf) return ;
if (u==pos[S])
{
f[u]=val2[u];
return ;
}
for (int i=now.head[u];i;i=now.pre[i])
{
int v=now.to[i];
mx(v);
f[u]=max(f[u],f[v]+val2[u]);
}
}
void work()
{
S=read(),P=read();
for (int i=1;i<=size;i++) f[i]=-inf;
//注意用memset置的inf與實際的inf的大小是不一樣的,
//這裏的記憶化搜索需要判斷是否來過(?==inf),就不能用memset,因爲要保證一樣
int ans=0;
for (int i=1;i<=P;i++)
{
int u=read();
mx(pos[u]);
ans=max(ans,f[pos[u]]);
}
printf("%d",ans);
}
int main()
{
init();//讀入
for (int i=1;i<=n;i++) if (!dfn[i]) dfs(i);//求出強連通分量 ,注意必須有這個循環!!!
work_graph();//縮點
work();//記憶花搜索,求出這些點的路徑最大權值
return 0;
}
總結
1:這題wa了好幾次,原因是縮點,只從1開始dfs了,實際上,可能會有許許多多的塊,應該再各個部分都dfs一下!!!!強連通分量必須加那個循環!!!
2:這道題寫了,鄰接表的結構體,感覺對於縮點的題更爲方便。
3:注意memset出的inf和實際的inf是不一樣的,所以如果需要判斷是否等於inf,在初始賦值的時候不能用memset。