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 }

 

 

你可能感兴趣的:(2007)