【bzoj 1093】: [ZJOI2007]最大半连通子图
2014-11-26 21:08
357 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=1093
啊哈,自己想出来了
显然的是,强联通子图半连通子图
所以可以考虑先缩点为DAG
然后YY一下,半连通子图是DAG上的一条链
问题转化为求DAG上最长路及其个数
开始写的点权spfa,发现没有必要
DAG上最长路直接DP即可
第一次wa掉了,没有处理重边
这道题学习一下缩点后的重边处理
啊哈,自己想出来了
显然的是,强联通子图半连通子图
所以可以考虑先缩点为DAG
然后YY一下,半连通子图是DAG上的一条链
问题转化为求DAG上最长路及其个数
开始写的点权spfa,发现没有必要
DAG上最长路直接DP即可
第一次wa掉了,没有处理重边
这道题学习一下缩点后的重边处理
//#define _TEST _TEST #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <cmath> #include <algorithm> #include <stack> using namespace std; /************************************************ Code By willinglive Blog:http://willinglive.cf ************************************************/ #define rep(i,l,r) for(int i=l,___t=(r);i<=___t;i++) #define per(i,r,l) for(int i=r,___t=(l);i>=___t;i--) #define MS(arr,x) memset(arr,x,sizeof(arr)) #define LL long long #define INE(i,u,e) for(int i=head[u];~i;i=e[i].next) inline const int read() { int r=0,k=1;char c=getchar(); for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1; for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0'; return k*r; } ///////////////////////////////////////////////// const int M=1000010,N=100010; int n,m,mod; int scc; int id ,sz ; namespace Graph {////////////////////////// struct edge{int v,next;}e[M]; int head ,k; void adde(int u,int v){e[k].v=v;e[k].next=head[u];head[u]=k++;} int dfn ,low ,ind; int s ,top; bool ins ; void tarjan(int u) { dfn[u]=low[u]=++ind; s[++top]=u; ins[u]=1; INE(i,u,e) { int v=e[i].v; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(ins[v] && low[u]>dfn[v]) low[u]=dfn[v]; } if(dfn[u]==low[u]) { int v; ++scc; do { v=s[top--]; ins[v]=0; id[v]=scc; sz[scc]++; }while(v!=u); } } }////////////////////////// namespace DAG {////////////////////////// struct edge{int v,next;}e[M]; int head ,k; void adde(int u,int v){e[k].v=v;e[k].next=head[u];head[u]=k++;} int in ; stack<int>s; int f ,dis ,fa ; bool inq ; }////////////////////////// ///////////////////////////////////////////////// ///////////////////////////////////////////////// void input() { MS(Graph::head,-1); MS(DAG::head,-1); using namespace Graph; n=read(); m=read(); mod=read(); int u,v; rep(i,1,m) { u=read(); v=read(); adde(u,v); } } void solve() { {// 1 using namespace Graph; rep(i,1,n) if(!dfn[i]) tarjan(i); rep(u,1,n) { INE(i,u,e) { int v=e[i].v; if(id[u]!=id[v]) { DAG::adde(id[u],id[v]); DAG::in[id[v]]++; } } } } {// 2 using namespace DAG; rep(i,1,scc) if(!in[i]) s.push(i),dis[i]=sz[i],f[i]=1; while(!s.empty()) { int u=s.top(); s.pop(); INE(i,u,e) { int v=e[i].v; in[v]--; if(!in[v]) s.push(v); if(dis[v]<dis[u]+sz[v]) { dis[v]=dis[u]+sz[v]; f[v]=f[u]; } else if(dis[v]==dis[u]+sz[v] && fa[v]!=u) f[v]=(f[v]+f[u])%mod; fa[v]=u; } } int mx=*max_element(&dis[1],&dis[scc+1]); int ans=0; rep(i,1,scc) if(dis[i]==mx) ans=(ans+f[i])%mod; printf("%d\n%d\n",mx,ans); } } ///////////////////////////////////////////////// int main() { #ifndef _TEST freopen("std.in","r",stdin); freopen("std.out","w",stdout); #endif input(),solve(); return 0; }
相关文章推荐
- 【BZOJ】1093: [ZJOI2007]最大半连通子图(tarjan+拓扑序)
- BZOJ1093 [ZJOI2007]最大半连通子图
- bzoj1093【ZJOI2007】最大半连通子图
- BZOJ 1093: [ZJOI2007]最大半连通子图
- BZOJ 1093 ZJOI2007 最大半连通子图 Tarjan+动态规划
- 【BZOJ 1093】 [ZJOI2007]最大半连通子图
- bzoj 1093: [ZJOI2007]最大半连通子图
- bzoj 1093 [ZJOI2007]最大半连通子图(scc+DP)
- BZOJ 1093 ZJOI 2007 最大半连通子图 强联通分量+拓扑图DP
- 【bzoj1093】 [ZJOI2007]最大半连通子图
- BZOJ 1093 ZJOI 2007 最大半连通子图 DP
- BZOJ1093 [ZJOI2007]最大半连通子图 【tarjan缩点 + DAG最长路计数】
- [bzoj1093][ZJOI2007]最大半连通子图 Tarjan,DP
- BZOJ 1093 [ZJOI2007]最大半连通子图
- Tarjan-bzoj1093: [ZJOI2007]最大半连通子图
- bzoj1093: [ZJOI2007]最大半连通子图
- [BZOJ]1093: [ZJOI2007]最大半连通子图 Tarjan缩点+拓扑图DP
- 【BZOJ1093】[ZJOI2007]最大半连通子图【SCC】【DAG】【DP】
- 【BZOJ 1093】【ZJOI 2007】【最大半连通子图】【tarjan强连通分量】【拓扑排序dp】
- bzoj1093[ZJOI2007]最大半连通子图 tarjan+拓补排序