BZOJ 1093 最大半連通子圖 題解

1093: [ZJOI2007]最大半連通子圖

Time Limit: 30 Sec  Memory Limit: 162 MB
Submit: 2767  Solved: 1095
[Submit][Status][Discuss]

Description

  一個有向圖G=(V,E)稱爲半連通的(Semi-Connected),若是知足:?u,v∈V,知足u→v或v→u,即對於圖中任意
兩點u,v,存在一條u到v的有向路徑或者從v到u的有向路徑。若G'=(V',E')知足V'?V,E'是E中全部跟V'有關的邊,
則稱G'是G的一個導出子圖。若G'是G的導出子圖,且G'半連通,則稱G'爲G的半連通子圖。若G'是G全部半連通子圖
中包含節點數最多的,則稱G'是G的最大半連通子圖。給定一個有向圖G,請求出G的最大半連通子圖擁有的節點數K
,以及不一樣的最大半連通子圖的數目C。因爲C可能比較大,僅要求輸出C對X的餘數。php

Input

  第一行包含兩個整數N,M,X。N,M分別表示圖G的點數與邊數,X的意義如上文所述接下來M行,每行兩個正整
數a, b,表示一條有向邊(a, b)。圖中的每一個點將編號爲1,2,3…N,保證輸入中同一個(a,b)不會出現兩次。N ≤1
00000, M ≤1000000;對於100%的數據, X ≤10^8ios

Output

  應包含兩行,第一行包含一個整數K。第二行包含整數C Mod X.ide

Sample Input

6 6 20070603
1 2
2 1
1 3
2 4
5 6
6 4

Sample Output

3
3

HINT

 

Source

——————————————————我是分割線————————————————————
spfa+dp+tarjan

先縮點,從新建圖,使其成爲一個 DAG,spa

DAG 中每一個點有一個點權表示這個點是原圖中的幾個點縮成的code

新圖中的一個最大半連通子圖,必然是新圖中的一個最長鏈(點權和最大),blog

知道了這點以後,DP 就好了,ip

相似於樹形 DP,先求出從每一個點出發,能走的最長鏈是多長,統計最長的那條就是最大半連通子圖的點的數量了,ci

至於怎麼求有多少個最大半連通子圖,也是同樣的 DP 就行,在上一步的 DP 以後,再 DP 一遍,統計每一個點出發能走出多少條最長鏈,最後統計求和便可get

  1 /*
  2     Problem:
  3     OJ:
  4     User:    S.B.S.
  5     Time:
  6     Memory:
  7     Length:
  8 */
  9 #include<iostream>
 10 #include<cstdio>
 11 #include<cstring>
 12 #include<cmath>
 13 #include<algorithm>
 14 #include<queue>
 15 #include<cstdlib>
 16 #include<iomanip>
 17 #include<cassert>
 18 #include<climits>
 19 #include<functional>
 20 #include<bitset>
 21 #include<vector>
 22 #include<list>
 23 #include<map>
 24 #define F(i,j,k) for(int i=j;i<=k;i++)
 25 #define M(a,b) memset(a,b,sizeof(a))
 26 #define FF(i,j,k) for(int i=j;i>=k;i--)
 27 #define BUG system("pause")
 28 #define maxn 200000
 29 #define inf 0x3f3f3f3f
 30 #define maxm 5000000
 31 //#define LOCAL
 32 using namespace std;
 33 int read(){
 34     int x=0,f=1;char ch=getchar();
 35     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 36     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 37     return x*f;
 38 }
 39 int head[maxn],to[maxm],next[maxm];
 40 int dfn[maxn],low[maxn];
 41 int st[maxm],ed[maxm];
 42 int n,m,cnt,ans,anss,mod;
 43 int tot,belong[maxn],t,p,stk[maxn],val[maxn];
 44 bool instk[maxn];
 45 int num[maxn],in[maxn],dp[maxn],q[maxm],vis[maxn];
 46 inline void add(int u,int v)
 47 {
 48     to[cnt]=v; 
 49     next[cnt]=head[u]; 
 50     head[u]=cnt++;
 51 }
 52 inline void init()
 53 {
 54     memset(head,-1,sizeof(head));cnt=0;
 55     cin>>n>>m>>mod;
 56     for(int i=1;i<=m;i++)
 57     {
 58         cin>>st[i]>>ed[i];
 59         add(st[i],ed[i]);
 60     }
 61 }
 62 inline void dfs(int u)
 63 {
 64     low[u]=dfn[u]=++t;
 65     stk[++p]=u; instk[u]=true;
 66     for(int i=head[u];i!=-1;i=next[i])
 67     {
 68         if(!dfn[to[i]])
 69         {
 70             dfs(to[i]);
 71             low[u]=min(low[u],low[to[i]]);
 72         }
 73         else if(instk[to[i]]) low[u]=min(low[u],dfn[to[i]]);
 74     }
 75     if(dfn[u]==low[u])
 76     {
 77         tot++;
 78         int tmp=-1;
 79         while(tmp!=u)
 80         {
 81             tmp=stk[p--];
 82             belong[tmp]=tot;
 83             val[tot]++;
 84             instk[tmp]=false;
 85         }
 86     }
 87 }
 88 inline void topsort()
 89 {
 90     int h=1,t=1,u;
 91     for(int i=1;i<=tot;i++)
 92         if(in[i]==0)
 93         {
 94             q[t++]=i;
 95             dp[i]=val[i];
 96             num[i]=1;
 97         }
 98     while(h<t)
 99     {
100         u=q[h++];
101         for(int i=head[u];i!=-1;i=next[i])
102         {
103             in[to[i]]--;
104             if(in[to[i]]==0) q[t++]=to[i];
105             if(vis[to[i]]==u) continue;
106             if(dp[to[i]]<dp[u]+val[to[i]])
107             {
108                 dp[to[i]]=dp[u]+val[to[i]];
109                 num[to[i]]=num[u];
110             }
111             else if(dp[to[i]]==dp[u]+val[to[i]])
112             {
113                 num[to[i]]=(num[to[i]]+num[u])%mod;
114             }
115             vis[to[i]]=u;
116         }
117     }
118 }
119 inline void go()
120 {
121     for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i);
122     memset(head,-1,sizeof(head));cnt=0;
123     for(int i=1;i<=m;i++)
124         if(belong[st[i]]!=belong[ed[i]])
125         {
126             add(belong[st[i]],belong[ed[i]]);
127             in[belong[ed[i]]]++;
128         }
129     topsort();
130     for(int i=1;i<=tot;i++)
131     {
132         if(dp[i]>ans)
133         {
134             ans=dp[i];
135             anss=num[i];
136         }
137         else if(dp[i]==ans) anss=(anss+num[i])%mod;
138     }
139     cout<<ans<<endl<<anss<<endl;
140 }
141 int main()
142 {
143     std::ios::sync_with_stdio(false);//cout<<setiosflags(ios::fixed)<<setprecision(1)<<y;
144     #ifdef LOCAL
145     freopen("data.in","r",stdin);
146     freopen("data.out","w",stdout);
147     #endif
148     init();
149     go();
150     return 0;
151 }
View Code
相關文章
相關標籤/搜索