bzoj1093: [ZJOI2007]最大半连通子图
Description
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
1 2
2 1
1 3
2 4
5 6
6 4
Sample Output
3
3
3
HINT
对于100%的数据, N ≤100000, M ≤1000000;对于100%的数据, X ≤10^8。
题解:
先进行缩点,得到一张DAG,然后最大半连通子图就是这个DAG包含点数最多的链,dp一下即可
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define maxn 100005 7 #define maxm 1000005 8 using namespace std; 9 char ch; 10 bool ok; 11 void read(int &x){ 12 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 13 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 14 if (ok) x=-x; 15 } 16 int n,m,mod,a,b; 17 int idx,dfn[maxn],low[maxn],top,stack[maxn],cnt,belong[maxn],sum[maxn]; 18 bool in[maxn]; 19 int num; 20 struct Edge{ 21 int u,v; 22 inline bool operator==(Edge b){return u==b.u&&v==b.v;} 23 }edge[maxm]; 24 inline bool cmp(Edge a,Edge b){ 25 if (a.u==b.u) return a.v<b.v; 26 return a.u<b.u; 27 } 28 int head,tail,list[maxn],f[maxn],g[maxn],deg[maxn]; 29 struct Graph{ 30 int tot,now[maxn],pre[maxm],son[maxm]; 31 void put(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;} 32 void dfs(int u){ 33 dfn[u]=low[u]=++idx,stack[++top]=u,in[u]=1; 34 for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) 35 if (!dfn[v]) dfs(v),low[u]=min(low[u],low[v]); 36 else if (in[v]) low[u]=min(low[u],dfn[v]); 37 if (dfn[u]==low[u]){ 38 int v; ++cnt; 39 do{v=stack[top--],in[v]=0,belong[v]=cnt,sum[cnt]++;}while(v!=u); 40 } 41 } 42 void get(){ 43 for (int u=1;u<=n;u++) 44 for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) 45 if (belong[u]!=belong[v]) edge[++num]=(Edge){belong[u],belong[v]}; 46 sort(edge+1,edge+num+1,cmp),num=unique(edge+1,edge+num+1)-edge-1; 47 } 48 void calc(){ 49 head=0,tail=0; 50 for (int i=1;i<=cnt;i++) if (!deg[i]) list[++tail]=i,g[i]=1; 51 while (head<tail){ 52 int u=list[++head]; 53 f[u]+=sum[u]; 54 for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]){ 55 if (f[v]<f[u]) f[v]=f[u],g[v]=g[u]; 56 else if (f[v]==f[u]) g[v]+=g[u],g[v]%=mod; 57 deg[v]--; 58 if (!deg[v]) list[++tail]=v; 59 } 60 } 61 int ans1=0,ans2=0; 62 for (int i=1;i<=cnt;i++) ans1=max(ans1,f[i]); 63 printf("%d\n",ans1); 64 for (int i=1;i<=cnt;i++) if (ans1==f[i]) ans2+=g[i],ans2%=mod; 65 printf("%d\n",ans2); 66 } 67 }G1,G2; 68 int main(){ 69 read(n),read(m),read(mod); 70 for (int i=1;i<=m;i++) read(a),read(b),G1.put(a,b); 71 for (int i=1;i<=n;i++) if (!dfn[i]) G1.dfs(i); 72 G1.get(); 73 for (int i=1;i<=num;i++) G2.put(edge[i].u,edge[i].v),deg[edge[i].v]++; 74 G2.calc(); 75 return 0; 76 }