这个题是比较套路的做法啦,建反图后缩点+拓扑排序嘛,对于所有处在$size>=2$的SCC中的点都是无限解(可以一直绕)
然后注意统计的时候的小细节,因为无限解/大解也要输出,所以我们把这些点统一统计成36501,然后所有的方案都对36501取min就可以很方便的输出了
1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=1000005,INF=36501; 7 int P[N],Noww[N],Goal[N]; 8 int p[N],noww[N],goal[N]; 9 int dfn[N],low[N],col[N],deg[N],inf[N]; 10 int stk[N],ins[N],que[N],outp[N],dp[N]; 11 int n,m,c,f,b,t1,t2,cnt,Cnt,tot,top,ans; 12 void link(int f,int t) 13 { 14 noww[++cnt]=p[f]; 15 goal[cnt]=t,p[f]=cnt; 16 } 17 void relink(int f,int t) 18 { 19 Noww[++Cnt]=P[f]; 20 Goal[Cnt]=t,P[f]=Cnt; 21 } 22 void Tarjan_SCC(int nde) 23 { 24 dfn[nde]=low[nde]=++tot; 25 stk[++top]=nde,ins[nde]=true; 26 for(int i=p[nde];i;i=noww[i]) 27 if(!dfn[goal[i]]) 28 Tarjan_SCC(goal[i]),low[nde]=min(low[nde],low[goal[i]]); 29 else if(ins[goal[i]]) 30 low[nde]=min(low[nde],low[goal[i]]); 31 if(dfn[nde]==low[nde]) 32 { 33 c++; int tmp; 34 do 35 { 36 tmp=stk[top--]; 37 ins[tmp]=false; 38 col[tmp]=c; 39 }while(nde!=tmp); 40 } 41 } 42 int main () 43 { 44 scanf("%d%d",&n,&m),b=-1; 45 for(int i=1;i<=m;i++) 46 scanf("%d%d",&t1,&t2),link(t2,t1); 47 for(int i=1;i<=n+1;i++) 48 if(!dfn[i]) Tarjan_SCC(i); 49 for(int i=1;i<=n+1;i++) 50 for(int j=p[i];j;j=noww[j]) 51 if(col[i]!=col[goal[j]]) 52 { 53 relink(col[i],col[goal[j]]); 54 deg[col[goal[j]]]++; 55 } 56 else inf[col[i]]=true; 57 for(int i=1;i<=c;i++) 58 if(!deg[i]) que[++b]=i; 59 dp[col[n+1]]=1; 60 while(f<=b) 61 { 62 int tn=que[f++]; 63 if(inf[tn]&&dp[tn]) dp[tn]=INF; 64 for(int i=P[tn];i;i=Noww[i]) 65 { 66 dp[Goal[i]]=min(dp[Goal[i]]+dp[tn],INF); 67 if(!(--deg[Goal[i]])) que[++b]=Goal[i]; 68 } 69 } 70 for(int i=1;i<=c;i++) ans=max(ans,dp[i]); 71 for(int i=1;i<=n;i++) 72 if(dp[col[i]]==ans) outp[++outp[0]]=i; 73 ans>36500?printf("zawsze"):printf("%d",ans); 74 puts(""),printf("%d\n",outp[0]); 75 for(int i=1;i<=outp[0];i++) 76 printf("%d ",outp[i]); 77 return 0; 78 }
原文地址:https://www.cnblogs.com/ydnhaha/p/9839528.html
时间: 2024-10-17 08:47:28