写这篇文章才发现我自己原来一直把tarjan拼成targin(targin对不起!)
这个缩点调了我两个多小时,最后还是看题解慢慢调对的。这个题其实题意很简单,就是求一个类似于最长路径的东西,那么首先我们可以把能够互相到达的点(即强连通分量)弄成一个点,重新建图,弄成一个有向无环图,然后在上面搜索(因为点少了很多而且没环)其中的艰辛其实很多,但是直接附上代码吧
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int p[100001]={0},dfn[100001]={0},s[100001]={0},co[100001]={0},nxt[100001]={0},dp[100001]={0};
int low[100001]={0},head[100001]={0},d[100001]={0},to[100001]={0},vis[100001]={0},x[100001]={0},y[100001]={0};
int n,m,tmp=0,num=0,top=0,col=0,max=-1;
int min(int x,int y)
{
if(x>y)
return y;
else return x;
}
int add(int x,int y)
{
tmp++;
to[tmp]=y;
nxt[tmp]=head[x];
head[x]=tmp;
return 0;
}
int targin(int i)
{
int j,t;
num++;top++;
dfn[i]=num;low[i]=num;
s[top]=i;
for(j=head[i];j;j=nxt[j])
{
t=to[j];
if(dfn[t]==0)
{
targin(t);
low[i]=min(low[i],low[t]);
}
else if(co[t]==0)
{
low[i]=min(low[i],dfn[t]);
}
}
if(dfn[i]==low[i])
{
col++;co[i]=col;
while(s[top]!=i)
{
co[s[top]]=col;
top--;
}
top--;
}
return 0;
}
int dfs(int i)
{
int j,maxsum=0;
if(dp[i]!=0) return 0;
dp[i]=d[i];
for(j=head[i];j;j=nxt[j])
{
if(dp[to[j]]==0)
dfs(to[j]);
if(dp[to[j]]>maxsum)
maxsum=dp[to[j]];
}
dp[i]+=maxsum;
return 0;
}
int main()
{
int i,j,t1,t2;
memset(d,0,sizeof(d));
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&p[i]);
for(i=1;i<=m;i++)
{
scanf("%d%d",&x[i],&y[i]);
if(x[i]!=y[i])
add(x[i],y[i]);
}
for(i=1;i<=n;i++)
if(dfn[i]==0)
targin(i);
for(i=1;i<=n;i++)
d[co[i]]+=p[i];
memset(nxt,0,sizeof(nxt));
memset(to,0,sizeof(to));
memset(head,0,sizeof(head));
tmp=0;
for(i=1;i<=m;i++)
{
if(co[x[i]]!=co[y[i]])
add(co[x[i]],co[y[i]]);
}
for(i=1;i<=col;i++)
if(dp[i]==0)
{
dfs(i);
if(dp[i]>max)
max=dp[i];
}
printf("%d",max);
return 0;
}
(tarjan绝对是我开数组开的最多的一个算法)