【BZOJ1093】[ZJOI2007]最大半聯通子圖(Tarjan,動態規劃)
阿新 • • 發佈:2018-10-04
() queue 有一個 ble class empty cpp 之間 names
【BZOJ1093】[ZJOI2007]最大半聯通子圖(Tarjan,動態規劃)
題面
BZOJ
洛谷
洛谷的討論裏面有一個好看得多的題面
題解
顯然強連通分量對於題目是沒有任何影響的,直接縮點就好了。
那麽接下來剩下的是一個\(DAG\),既然任意兩點之間都有一條路徑連接,在\(DAG\)上的體現就是這個玩意一定是一條鏈。隨便\(dp\)一下就好了。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> using namespace std; #define MAX 100100 #define MAXL 1000100 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } vector<int> E[MAX]; struct Line{int v,next;}e[MAXL]; int h[MAX],cnt=1; inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;} int dfn[MAX],low[MAX],S[MAX],G[MAX],sz[MAX],tim,top,gr,len[MAX]; int dg[MAX],p[MAX],f[MAX],g[MAX],tot; bool ins[MAX]; void Tarjan(int u) { S[++top]=u;dfn[u]=low[u]=++tim;ins[u]=true; for(int i=h[u];i;i=e[i].next) if(!dfn[e[i].v]) Tarjan(e[i].v),low[u]=min(low[u],low[e[i].v]); else if(ins[e[i].v]) low[u]=min(low[u],dfn[e[i].v]); if(dfn[u]==low[u]) { ++gr;int v; do{v=S[top--];ins[v]=false;G[v]=gr;++sz[gr];}while(u!=v); } } void Topsort() { queue<int> Q; for(int i=1;i<=gr;++i)if(!dg[i])Q.push(i),E[0].push_back(i),++len[0]; while(!Q.empty()) { int u=Q.front();Q.pop();p[++tot]=u; for(int i=0;i<len[u];++i) if(!--dg[E[u][i]])Q.push(E[u][i]); } } int n,m,MOD; int main() { n=read();m=read();MOD=read(); for(int i=1,u,v;i<=m;++i)u=read(),v=read(),Add(u,v); for(int i=1;i<=n;++i)if(!dfn[i])Tarjan(i); for(int u=1;u<=n;++u) for(int i=h[u];i;i=e[i].next) if(G[u]!=G[e[i].v]) E[G[u]].push_back(G[e[i].v]); for(int i=1;i<=gr;++i)sort(E[i].begin(),E[i].end()); for(int i=1;i<=gr;++i)len[i]=unique(E[i].begin(),E[i].end())-E[i].begin(); for(int i=1;i<=gr;++i) for(int j=0;j<len[i];++j) ++dg[E[i][j]]; Topsort(); for(int i=gr;~i;--i) { int u=p[i];f[u]=sz[u];g[u]=1; for(int j=0;j<len[u];++j) { int v=E[u][j]; if(f[u]<sz[u]+f[v]) f[u]=sz[u]+f[v],g[u]=g[v]; else if(f[u]==sz[u]+f[v]) g[u]=(g[u]+g[v])%MOD; } } printf("%d\n%d\n",f[0],g[0]); return 0; }
【BZOJ1093】[ZJOI2007]最大半聯通子圖(Tarjan,動態規劃)