思路:
(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; }