思路:
(1):先對原圖進行縮點,即把每個強連通分量縮成一個點,其權值為聯通分量裡面所有點的權值之和。
(2):縮點後重新構圖,並把每條又向邊上加上權值:sInsert(Belong[u],Belong[v],num[Belong[v]]);
(3):然後再重每個入度為零的點s(縮點後)進行SPFA求最長路,並更新答案ans=max(ans,max{dis[i]}+num[s]);
(4):最後的ans即是d答案。
CODE:
/*縮點+SFPA求最長路*//*AC代碼:63ms*/#include <iostream>#include <cstdio>#include <algorithm>#include <memory.h>#include <queue>#define MAXN 30005#define INF 1e8#define max(a,b) (a>b?a:b)using namespace std;struct edge{int u,v,w,next;}E[150005],sE[150005];int head[MAXN],ecnt;int shead[MAXN],secnt;//縮點後重新構圖int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN],dis[MAXN];int Index,scc,top,N,M;int num[MAXN];//縮點後每個強連通分量內的權值和int W[MAXN];int In[MAXN];int start[MAXN],cnt;bool Instack[MAXN];bool vis[MAXN];void Insert(int u,int v){E[ecnt].u=u;E[ecnt].v=v;E[ecnt].next=head[u];head[u]=ecnt++;}void sInsert(int u,int v,int w){sE[secnt].u=u;sE[secnt].v=v;sE[secnt].w=w;sE[secnt].next=shead[u];shead[u]=secnt++;}void Tarjan(int u){int i,v;Low[u]=DFN[u]=++Index;Stack[++top]=u;Instack[u]=true;for(i=head[u];i!=-1;i=E[i].next){v=E[i].v;if(!DFN[v]){Tarjan(v);if(Low[u]>Low[v])Low[u]=Low[v];}else if(Instack[v]&&Low[u]>DFN[v])Low[u]=DFN[v];}if(Low[u]==DFN[u]){scc++;do{v=Stack[top--];Instack[v]=false;Belong[v]=scc;num[scc]+=W[v];}while(u!=v);}return;}void Init(){int i,u,v;memset(head,-1,sizeof(head));ecnt=0;memset(shead,-1,sizeof(shead));secnt=0;for(i=1;i<=N;i++){scanf("%d",&W[i]);if(W[i]<0) W[i]=0;}for(i=1;i<=M;i++){scanf("%d%d",&u,&v);if(u!=v)Insert(u+1,v+1);}}void Shrink()//縮點+重新構圖{int i,u,v;memset(num,0,sizeof(num));memset(DFN,0,sizeof(DFN));memset(Instack,false,sizeof(Instack));memset(Low,0,sizeof(Low));Index=scc=top=0;for(i=1;i<=N;i++){if(!DFN[i]) Tarjan(i);}memset(In,0,sizeof(In));for(i=0;i<ecnt;i++){u=E[i].u;v=E[i].v;if(Belong[u]!=Belong[v]){sInsert(Belong[u],Belong[v],num[Belong[v]]);In[Belong[v]]++;}}cnt=0;for(i=1;i<=scc;i++){if(!In[i])start[++cnt]=i;//printf("%d %d\n",i,num[i]);}}queue<int>Q;int SPFA(int s){int i,u,v,w;while(!Q.empty()) Q.pop();memset(vis,false,sizeof(vis));for(i=1;i<=scc;i++)dis[i]=-INF;Q.push(s);dis[s]=0;vis[s]=true;while(!Q.empty()){//printf("&\n");u=Q.front();Q.pop();vis[u]=false;for(i=shead[u];i!=-1;i=sE[i].next){v=sE[i].v;w=sE[i].w;if(dis[v]<dis[u]+w){dis[v]=dis[u]+w;if(!vis[v]){Q.push(v);vis[v]=true;}}}}int res=0;for(i=1;i<=scc;i++)res=max(res,dis[i]);//printf("^^%d\n",res+W[s]);return res+num[s];}void Solve(){int i,ans=0;Shrink();//printf("*\n");for(i=1;i<=cnt;i++)ans=max(ans,SPFA(start[i]));printf("%d\n",ans);}int main(){while(scanf("%d%d",&N,&M)!=EOF){Init();Solve();}return 0;}