洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur
Tarjan缩点+拓扑排序
以后缩点后建图看n范围用vector ,或者直接用map+vector
结构体里数据要清空
代码:
#include <cstring> #include <cctype> #include <cstdio> #include <vector> #include <queue> #define N 100005 using namespace std; vector<int>G[N]; inline void Read(int &x) { register char ch=getchar(); for(x=0;!isdigit(ch);ch=getchar()); for(;isdigit(ch);x=x*10+ch-'0',ch=getchar()); } bool instack[N]; int n,m,ans,stack[N],low[N],dfn[N],col[N],sum[N],f1[N],f2[N],in1[N],in2[N],sumcol,tim,top; inline int min(int a,int b) {return a>b?b:a;} inline int max(int a,int b) {return a>b?a:b;} void tarjan(int x) { low[x]=dfn[x]=++tim; stack[++top]=x; instack[x]=true; for(int i=0;i<G[x].size();++i) { int v=G[x][i]; if(!dfn[v]) { tarjan(v); low[x]=min(low[x],low[v]); } else if(instack[v]) low[x]=min(low[x],dfn[v]); } if(low[x]==dfn[x]) { int k; sumcol++; do { k=stack[top--]; instack[k]=false; col[k]=sumcol; sum[sumcol]++; }while(k!=x); } } struct node { int f[N],in[N],cnt; struct Edge { int to; Edge * next; }*head[N],edge[N]; void ins(int u,int v) { in[v]++; edge[++cnt].next=head[u]; edge[cnt].to=v; head[u]=cnt+edge; } void tppx() { queue<int>q; for(int i=1;i<=sumcol;++i) {f[i]=0xefefefef;if(!in[i]) q.push(i);} f[col[1]]=sum[col[1]]; for(int now;!q.empty();) { now=q.front(); q.pop(); for(Edge * u=head[now];u;u=u->next) { int v=u->to; f[v]=max(f[v],f[now]+sum[v]); in[v]--; if(!in[v]) q.push(v); } } } node () { cnt=0; memset(in,0,sizeof(in)); memset(head,NULL,sizeof(head)); } }; node a,b; int main() { Read(n); Read(m); for(int x,y;m--;) { Read(x); Read(y); G[x].push_back(y); } for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;++i) { for(int j=0;j<G[i].size();++j) { int v=G[i][j]; if(col[i]!=col[v]) a.ins(col[i],col[v]),b.ins(col[v],col[i]); } } a.tppx(); b.tppx(); ans=sum[col[1]]; for(int i=1;i<=n;++i) { for(int j=0;j<G[i].size();++j) { int v=G[i][j]; ans=max(ans,a.f[col[v]]+b.f[col[i]]); } } printf("%d\n",ans-sum[col[1]]); return 0; }
我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。