1093: [ZJOI2007]最大半连通子图
Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 1986 Solved: 802
[Submit][Status][Discuss]
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。
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(' ') 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 }