poj 3160 Father Christmas flymouse

// 题目描述:
从武汉大学ACM集训队退役后,flymouse 做起了志愿者,帮助集训队做一些琐碎的事情,
比如打扫集训用的机房等等。当圣诞节来临时,flymouse打扮成圣诞老人给集训队员发放礼物。
集训队员住在校园通过宿舍的不同寝室里。为了节省体力,flymouse决定从某个寝室出发,沿着
一些有向路一个接一个地访问寝室并顺便发放礼物,直到所有集训队员的起始走遍为止。
以前flymouse在集训队的日子里,他给其他队员留下了不同的印象。他们中的一些人,比如
LiZhiXu,对flymouse的印象特别好,将会为他的好心唱赞歌;而其他一些人,比如snoopy,将
不会宽恕flymouse 的懒惰。flymouse 可以用一种安慰指数来量化他听了这些队员的话语后心情
是好还是坏(正数表示是心情好,负数表示心情坏)。当到达一个寝室时,他可以选择进入寝室、
发放礼物、倾听接收礼物的队员的话语,或者默默地绕开这个寝室。他可能会多次经过一个寝室,
但决不会第二次进入该寝室。他想知道在他发放礼物的整个旅程,他收获安慰指数的最大数量。


// 缩点 把强连通分量内的值加起来(负数就不加了吧 开始我没想到有负数 WA了)
// 然后就是 DAG(无回路有向图)的单源最长路径 这个简单dp了
// 先拓扑排序 根据拓扑排序进行dp 然后就OK了

#include <iostream> #include <algorithm> #include <queue> #include <stack> #include <math.h> #include <stdio.h> #include <string.h> using namespace std; #define MOD 1000000007 #define maxn 300100 #define maxm 30010 struct Edge{ int to; int next; Edge(){}; Edge(int u,int v){to=u;next=v;} }E[maxn]; stack<int> S; int V[maxm],num,sccV[maxm]; int belong[maxm]; int pre[maxm]; int dfst,scc; bool tag[maxm]; int in[maxm];//,out[maxm]; int val[maxm],sccval[maxm]; void init(int n){ dfst=scc=0; num=0; while(!S.empty()) S.pop(); for(int i=1;i<=n;i++){ V[i]=-1; pre[i]=0; belong[i]=0; } } void add(int u,int v){ E[num].to=v; E[num].next=V[u]; V[u]=num++; } void sccadd(int u,int v){ E[num].to=v; E[num].next=sccV[u]; sccV[u]=num++; } int tarjan(int u){ int lowu=pre[u]=++dfst; int v,e; S.push(u); for(e=V[u];e!=-1;e=E[e].next){ v=E[e].to; if(!pre[v]){ int lowv=tarjan(v); lowu=min(lowu,lowv); } else if(!belong[v]) lowu=min(lowu,pre[v]); } if(lowu==pre[u]){ scc++; sccval[scc]=0; for(;;){ int x=S.top();S.pop(); if(val[x]>0)// 记得把负数舍掉、居然还搞负数 害我wa了、去看了下讨论板才知道的、、
sccval[scc]
+=val[x];// scc 的val belong[x]=scc; if(x==u) break; } } return lowu; } int top[maxm],tn; void topsort(){ int i,e; tn=0; for(i=1;i<=scc;i++)tag[i]=0; while(1){ for(i=1;i<=scc;i++) if(!tag[i]&&!in[i]) break; if(i>scc) break; tag[i]=true; top[tn++]=i; for(e=sccV[i];e!=-1;e=E[e].next){ in[E[e].to]--; } } } int dis[maxm]; int main() { int n,m,T; int u,v; int i,j; //scanf("%d",&T); while(scanf("%d %d",&n,&m)!=EOF){ init(n); for(i=1;i<=n;i++){ scanf("%d",&val[i]); } for(i=1;i<=m;i++) { scanf("%d %d",&u,&v); add(u+1,v+1); } for(i=1;i<=n;i++) if(!pre[i]) tarjan(i); // for(i=1;i<=n;i++) printf("%d ",belong[i]); int ans=-MOD; for(i=1;i<=scc;i++) { in[i]=0; sccV[i]=-1; dis[i]=sccval[i]; ans=max(ans,dis[i]); } int e,u,v; for(i=1;i<=n;i++) { for(e=V[i];e!=-1;e=E[e].next){ u=belong[i]; v=belong[E[e].to]; if(u!=v){ in[v]++; // out[u]++;//,printf("v=%d ",v); sccadd(u,v); } } } topsort(); for(i=0;i<tn;i++){ u=top[i]; for(e=sccV[u];e!=-1;e=E[e].next){ v=E[e].to; if(dis[v]<dis[u]+sccval[v]){ dis[v]=dis[u]+sccval[v]; ans=max(dis[v],ans); } } } printf("%d ",ans); } return 0; }
原文地址:https://www.cnblogs.com/372465774y/p/3206427.html