BZOJ 1093 [ZJOI2007]最大半连通子图
以前做过poj的一个判断图是否为弱连通的题,然后,这个题和poj那个差不多。
先强连通缩点,然后重新构图,然后找出包含点数最多的链,统计个数即可,可以用拓扑排序搞~
pS:重新构图时有重边,然后导致统计方案数的重复。。wa了好久。。还是wzc神犇告诉我这个蒟蒻的。。
View Code
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 7 #define N 200000 8 #define M 5000000 9 #define BUG system("pause") 10 11 using namespace std; 12 13 int head[N],to[M],next[M]; 14 int dfn[N],low[N]; 15 int st[M],ed[M]; 16 int n,m,cnt,ans,ansnum,mod; 17 int divg,belong[N],t,p,stk[N],val[N]; 18 bool fg[N]; 19 int num[N],in[N],dp[N],q[M],vis[N]; 20 21 inline void add(int u,int v) 22 { 23 to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++; 24 } 25 26 inline void read() 27 { 28 memset(head,-1,sizeof head); cnt=0; 29 scanf("%d%d%d",&n,&m,&mod); 30 for(int i=1;i<=m;i++) 31 { 32 scanf("%d%d",&st[i],&ed[i]); 33 add(st[i],ed[i]); 34 } 35 } 36 37 inline void dfs(int u) 38 { 39 low[u]=dfn[u]=++t; 40 stk[++p]=u; fg[u]=true; 41 for(int i=head[u];~i;i=next[i]) 42 { 43 if(!dfn[to[i]]) 44 { 45 dfs(to[i]); 46 low[u]=min(low[u],low[to[i]]); 47 } 48 else if(fg[to[i]]) low[u]=min(low[u],dfn[to[i]]); 49 } 50 if(dfn[u]==low[u]) 51 { 52 divg++; 53 int tmp=-1; 54 while(tmp!=u) 55 { 56 tmp=stk[p--]; 57 belong[tmp]=divg; 58 val[divg]++; 59 fg[tmp]=false; 60 } 61 } 62 } 63 64 inline void topsort() 65 { 66 int h=1,t=1,u; 67 for(int i=1;i<=divg;i++) 68 if(in[i]==0) 69 { 70 q[t++]=i; 71 dp[i]=val[i]; 72 num[i]=1; 73 } 74 while(h<t) 75 { 76 u=q[h++]; 77 for(int i=head[u];~i;i=next[i]) 78 { 79 in[to[i]]--; 80 if(in[to[i]]==0) q[t++]=to[i]; 81 if(vis[to[i]]==u) continue;//有重边!! 82 if(dp[to[i]]<dp[u]+val[to[i]]) 83 { 84 dp[to[i]]=dp[u]+val[to[i]]; 85 num[to[i]]=num[u]; 86 } 87 else if(dp[to[i]]==dp[u]+val[to[i]]) 88 { 89 num[to[i]]=(num[to[i]]+num[u])%mod; 90 } 91 vis[to[i]]=u; 92 } 93 } 94 } 95 96 inline void go() 97 { 98 for(int i=1;i<=n;i++) 99 if(!dfn[i]) dfs(i); 100 memset(head,-1,sizeof head); cnt=0; 101 for(int i=1;i<=m;i++) 102 if(belong[st[i]]!=belong[ed[i]]) 103 { 104 add(belong[st[i]],belong[ed[i]]); 105 in[belong[ed[i]]]++; 106 } 107 topsort(); 108 for(int i=1;i<=divg;i++) 109 { 110 if(dp[i]>ans) 111 { 112 ans=dp[i]; 113 ansnum=num[i]; 114 } 115 else if(dp[i]==ans) ansnum=(ansnum+num[i])%mod; 116 } 117 printf("%d\n%d\n",ans,ansnum); 118 } 119 120 int main() 121 { 122 read(); 123 go(); 124 return 0; 125 }
没有人能阻止我前进的步伐,除了我自己!