BZOJ 4304 tarjan+topsort+bitset
我就是想骗一骗访问量
先Tarjan搞出来所有的强连通分量
正向连边 反向连边 topsort一发 搞出来每个点可以到哪些点 和哪些点可以到这个点
对于每条边 与一下 就是答案
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=2050,M=N*N; int n,m,T,jy,ans,r=1; int low[N],dfn[N],cnt,stk[N],vis[N],p[N],top; set<int>s; struct Edge{ bitset<N>f[N]; int mp[N][N],in[N]; void topsort(){ queue<int>q; for(int i=1;i<=T;i++)for(int j=1;j<=T;j++)if(mp[i][j])in[j]++; for(int i=1;i<=T;i++)if(!in[i])q.push(i); while(!q.empty()){ int t=q.front();q.pop(); for(int v=1;v<=T;v++)if(mp[t][v]){ in[v]--,f[v]|=f[t]; if(!in[v])q.push(v); } } } }e[3]; struct Road{int x,y;Road(int X=0,int Y=0):x(X),y(Y){};}rd[M]; void tarjan(int x){ low[x]=dfn[x]=++cnt,stk[++top]=x;vis[x]=1; for(int v=1;v<=n;v++)if(e[0].mp[x][v]){ if(!dfn[v])tarjan(v),low[x]=min(low[x],low[v]); else if(vis[v])low[x]=min(low[x],dfn[v]); }if(low[x]==dfn[x]){T++;do{jy=stk[top--],vis[jy]=0;p[jy]=T;e[1].f[T][jy]=e[2].f[T][jy]=1;}while(jy!=x);} } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++)scanf("%d%d",&rd[i].x,&rd[i].y),e[0].mp[rd[i].x][rd[i].y]=1; for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i); for(int i=1;i<=m;i++)if(p[rd[i].x]!=p[rd[i].y]) e[1].mp[p[rd[i].x]][p[rd[i].y]]=e[2].mp[p[rd[i].y]][p[rd[i].x]]=1; e[1].topsort();e[2].topsort(); for(int i=1;i<=m;i++){ int t=(int)(e[2].f[p[rd[i].x]]&e[1].f[p[rd[i].y]]).count(); if(ans<t)s.clear(),ans=t,s.insert(i); else if(ans==t)s.insert(i); } printf("%d\n%d\n",ans,(int)s.size()); for(set<int>::iterator it=s.begin();it!=s.end();it++,r++)printf("%d%c",*it,r==s.size()?'\n':' '); }