【题目】http://poj.org/problem?id=3249
【大意】给定一些点,点上有权值,点之间有一些有向边,求从0入读点到0出度点距离的最大值。
【思路】拓扑序之后,按照拓扑序来松弛dis。
【参考】https://blog.csdn.net/LuRiCheng/article/details/53149412
【重点】拓扑排序
【代码】
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int M=500005;
const int INF=2000000000;
class node
{
public:
int v,next;
} edge[M*10];
int ei;
int head[M];
int n;
int dis[M];
int w[M];
bool books[M]= {0};
bool bookt[M]= {0};
bool used[M]= {0};
int TPO[M],ti;
void addedge(int u,int v)
{
edge[++ei].v=v;
edge[ei].next=head[u];
head[u]=ei;
}
void topsort(int x)
{
used[x]=1;
for(int i=head[x]; i!=-1; i=edge[i].next)
{
int v=edge[i].v;
if(used[v]==0)
topsort(v);
}
TPO[ti++]=x;
return;
}
int main()
{
while(~scanf("%d",&n))
{
ti=0;
memset(head,-1,sizeof(head));
memset(books,0,sizeof(books));
memset(bookt,0,sizeof(bookt));
memset(used,0,sizeof(used));
int m;
scanf("%d",&m);
for(int i=1; i<=n; i++)
scanf("%d",&w[i]);
for(int i=0; i<m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
books[u]=1;
bookt[v]=1;
}
for(int i=1; i<=n; i++)
{
if(bookt[i]==0)
dis[i]=w[i];
else
dis[i]=-INF;
if(used[i]==0)
topsort(i);
}
for(int i=n-1; i>=0; i--)
{
int t=TPO[i];
for(int j=head[t]; j!=-1; j=edge[j].next)
{
int v=edge[j].v;
dis[v]=max(dis[v],dis[t]+w[v]);
}
}
int ans=-INF;
for(int i=1; i<=n; i++)
{
if(books[i]==0)
ans=max(ans,dis[i]);
}
printf("%d\n",ans);
}
}