前置知识
解法
缩点后原图就成为了一个有向无环图,此时每个点最多被经过一次,故在求最长路的过程中可以将点权和边权混着转移。
- 上篇题解用拓扑实现查找两点间最长路的做法正确性不会证,遂写了份 Dijkstra 求最长路。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define sort stable_sort
#define endl '\n'
struct node
{
ll nxt,to;
}e[1000010];
stack<ll>s;
ll head[1000010],dfn[1000010],low[1000010],ins[1000010],c[1000010],a[1000010],b[1000010],u[1000010],v[1000010],vis[1000010],dis[1000010],cnt=0,tot=0,ans=0;
void add(ll u,ll v)
{
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void tarjan(ll x)
{
ll k=0,i;
tot++;
dfn[x]=low[x]=tot;
ins[x]=1;
s.push(x);
for(i=head[x];i!=0;i=e[i].nxt)
{
if(dfn[e[i].to]==0)
{
tarjan(e[i].to);
low[x]=min(low[x],low[e[i].to]);
}
else
{
if(ins[e[i].to]==1)
{
low[x]=min(low[x],dfn[e[i].to]);
}
}
}
if(dfn[x]==low[x])
{
ans++;
while(x!=k)
{
k=s.top();
ins[k]=0;
c[k]=ans;
b[ans]+=a[k];
s.pop();
}
}
}
void dijkstra(ll st)
{
ll x,i;
memset(vis,0,sizeof(vis));
memset(dis,-0x3f,sizeof(dis));
priority_queue<pair<ll,ll> >q;
dis[st]=b[st];
q.push(make_pair(dis[st],st));
while(q.empty()==0)
{
x=q.top().second;
q.pop();
if(vis[x]==0)
{
vis[x]=1;
for(i=head[x];i!=0;i=e[i].nxt)
{
if(dis[e[i].to]<dis[x]+b[e[i].to])
{
dis[e[i].to]=dis[x]+b[e[i].to];
q.push(make_pair(dis[e[i].to],e[i].to));
}
}
}
}
}
int main()
{
ll n,m,st,ed,i;
cin>>n>>m>>st>>ed;
for(i=1;i<=n;i++)
{
cin>>a[i];
}
for(i=1;i<=m;i++)
{
cin>>u[i]>>v[i];
add(u[i],v[i]);
}
for(i=1;i<=n;i++)
{
if(dfn[i]==0)
{
tarjan(i);
}
}
cnt=0;
memset(e,0,sizeof(e));
memset(head,0,sizeof(head));
for(i=1;i<=m;i++)
{
if(c[u[i]]!=c[v[i]])
{
add(c[u[i]],c[v[i]]);
}
}
dijkstra(c[st]);
cout<<dis[c[ed]]<<endl;
return 0;
}
标签:1000010,cnt,题解,ll,st,Travels,GOODA,low,dis
From: https://www.cnblogs.com/The-Shadow-Dragon/p/18301280