BZOJ 1093 [ZJOI2007]最大半连通子图

1093: [ZJOI2007]最大半连通子图

Time Limit: 30 Sec  Memory Limit: 162 MB
Submit: 1986  Solved: 802
[Submit][Status][Discuss]

Description

BZOJ 1093 [ZJOI2007]最大半连通子图_第1张图片

Input

第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述。接下来M行,每行两个正整数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。

Output

应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.

Sample Input

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

Sample Output

3
3

HINT

 

对于100%的数据, N ≤100000, M ≤1000000;对于100%的数据, X ≤10^8。

 

Source

题解:缩点dp。注意处理好大点间的重边。

你问我写哪种dp?首推topo啊!记忆化什么的常数大的。。。(雾

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<stack>
 6 #include<queue>
 7 #include<cstring>
 8 #define PAU putchar(' ')
 9 #define ENT putchar('\n')
10 #define MSE(a,b) memset(a,b,sizeof(a))
11 #define REN(x) for(ted*e=fch[x];e;e=e->nxt)
12 #define REN2(x) for(ted*e=fch2[x];e;e=e->nxt)
13 #define TIL(x) for(int i=1;i<=x;i++)
14 #define ALL(x) for(int j=1;j<=x;j++)
15 using namespace std;
16 const int maxn=100000+10,maxm=1000000+10,inf=1e9;
17 struct ted{int x,y;ted*nxt;}adj[maxm],adj2[maxm],*fch[maxn],*fch2[maxn],*ms=adj,*ms2=adj2;
18 void add(int x,int y){*ms=(ted){x,y,fch[x]};fch[x]=ms++;return;}int in[maxn];
19 void add2(int x,int y){*ms2=(ted){x,y,fch2[x]};fch2[x]=ms2++;in[y]++;return;}
20 int dfn[maxn],low[maxn],beg[maxn],siz[maxn],scc,cz,f[maxn],g[maxn],vis[maxn],mod;bool ins[maxn];stack<int>S;
21 void tarjan(int x){
22     dfn[x]=low[x]=++cz;ins[x]=true;S.push(x);REN(x){int v=e->y;
23         if(!dfn[v])tarjan(v),low[x]=min(low[x],low[v]);else if(ins[v])low[x]=min(low[x],dfn[v]);
24     }if(low[x]==dfn[x]){scc++;int t;
25         do beg[t=S.top()]=scc,ins[t]=false,S.pop(),siz[scc]++;while(t!=x);
26     }return;
27 }
28 int n,m;
29 void rebuild(){
30     TIL(n)REN(i)if(beg[i]!=beg[e->y])add2(beg[i],beg[e->y]);return;
31 }
32 void topodp(){
33     queue<int>Q;TIL(scc)if(!in[i])Q.push(i);TIL(scc)f[i]=siz[i],g[i]=1;
34     while(!Q.empty()){
35         int x=Q.front();Q.pop();REN2(x){int v=e->y;
36             if(--in[v]==0)Q.push(v);
37             if(vis[v]!=x){vis[v]=x;
38                 if(f[x]+siz[v]>f[v])f[v]=f[x]+siz[v],g[v]=g[x];
39                 else if(f[x]+siz[v]==f[v])(g[v]+=g[x])%=mod;
40             }
41         }
42     }return;
43 }
44 inline int read(){
45     int x=0;bool sig=true;char ch=getchar();
46     for(;!isdigit(ch);ch=getchar())if(ch=='-')sig=false;
47     for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';return sig?x:-x;
48 }
49 inline void write(int x){
50     if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x;
51     int len=0;static int buf[20];while(x)buf[len++]=x%10,x/=10;
52     for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return;
53 }
54 int main(){
55     n=read();m=read();mod=read();int x,y;
56     TIL(m)x=read(),y=read(),add(x,y);
57     TIL(n)if(!dfn[i])tarjan(i);rebuild();topodp();
58     int mx=-inf,ans;
59     TIL(scc){
60         if(mx<f[i])mx=f[i],ans=g[i];
61         else if(f[i]==mx)(ans+=g[i])%=mod;
62     }write(mx);ENT;write(ans);
63     return 0;
64 }

 

你可能感兴趣的:(BZOJ 1093 [ZJOI2007]最大半连通子图)