BZOJ 1093: [ZJOI2007]最大半连通子图
2014-09-01 10:40
218 查看
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1093
首先我们将原图求强连通然后缩点,显然我们在一个强连通里面所有的点都取,然后要在缩点后的图中取一条权值和最大的链,直接dp就行了。
代码:
首先我们将原图求强连通然后缩点,显然我们在一个强连通里面所有的点都取,然后要在缩点后的图中取一条权值和最大的链,直接dp就行了。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <stack> #include <string.h> #include <queue> #include <vector> #include <algorithm> #include <cassert> #include <set> #include <map> #include <cmath> #include <ctime> using namespace std; #define rep(i,a,b) for(int i=(a);i<(b);++i) #define rrep(i,a,b) for(int i=(a);i>=(b);--i) #define clr(a,x) memset(a,(x),sizeof(a)) #define eps 1e-8 #define LL long long #define mp make_pair const int maxn=100000+5; struct Node { int v; Node * next; }*first[maxn],edges[maxn*20]; int ptr; vector<int> adj[maxn]; void add(int u,int v) { edges[++ptr].v=v; edges[ptr].next=first[u]; first[u]=&edges[ptr]; } int n,m,mod; void input() { ptr=0; clr(first,0); while(m--) { int u,v; scanf("%d%d",&u,&v); add(u,v); } } int sccno[maxn],low[maxn],scc_cnt,dfn,pre[maxn]; vector<int> scc[maxn]; stack<int> S; inline int min(int a,int b) { return a<b?a:b; } inline int max(int a,int b) { return a>b?a:b; } int dfs(int u) { pre[u]=low[u]=++dfn; S.push(u); for(Node*p=first[u];p;p=p->next) { int v=p->v; if(!pre[v]) low[u]=min(low[u],dfs(v)); else if(!sccno[v]) low[u]=min(low[u],pre[v]); } if(low[u]==pre[u]) { scc[++scc_cnt].clear(); for(;;) { int x=S.top(); S.pop(); sccno[x]=scc_cnt; scc[scc_cnt].push_back(x); if(x==u) break; } } return low[u]; } void find_scc() { clr(sccno,0); clr(pre,0); clr(low,0); dfn=scc_cnt=0; rep(i,1,n+1) if(!pre[i]) dfs(i); } int ind[maxn],q[maxn],front,rear; int value[maxn]; bool vis[maxn]; void build() { clr(vis,0); clr(ind,0); rep(i,1,scc_cnt+1) { vis[i]=true; S.push(i); adj[i].clear(); value[i]=scc[i].size(); rep(j,0,scc[i].size()) { int u=scc[i][j]; for(Node * p=first[u];p;p=p->next) { int v=p->v; if(!vis[sccno[v]]) { ++ind[sccno[v]]; adj[sccno[u]].push_back(sccno[v]); S.push(sccno[v]); } vis[sccno[v]]=true; } } while(S.size()) { vis[S.top()]=false; S.pop(); } } } LL sum[maxn],dp[maxn]; void solve() { find_scc(); build(); front=rear=0; n=scc_cnt; rep(i,1,n+1) if(ind[i]==0) q[rear++]=i; while(front<rear) { int u=q[front++]; rep(i,0,adj[u].size()) { int v=adj[u][i]; if(--ind[v]==0) q[rear++]=v; } } clr(sum,0); clr(dp,0); rrep(i,rear-1,0) { int u=q[i]; dp[u]=value[u]; if(adj[u].size()==0) { sum[u]=1; continue; } LL num=0,maxsize=0; rep(j,0,adj[u].size()) { int v=adj[u][j]; if(maxsize<dp[v]) { maxsize=dp[v]; num=sum[v]; } else if(maxsize==dp[v]) num=(num+sum[v])%mod; } dp[u] += maxsize; sum[u] = num; } LL num=0,maxsize=0; rep(i,1,n+1) if(dp[i]>maxsize) { maxsize=dp[i]; num=sum[i]; } else if(dp[i]==maxsize) { num+=sum[i]; num%=mod; } printf("%lld\n%lld\n",maxsize,num); } int main() { // freopen("in.txt","r",stdin); while(scanf("%d%d%d",&n,&m,&mod)==3) { input(); solve(); } }
相关文章推荐
- 【连通分量】BZOJ 1093: [ZJOI2007]最大半连通子图
- BZOJ1093: [ZJOI2007]最大半连通子图
- 【BZOJ】1093: [ZJOI2007]最大半连通子图(tarjan+拓扑序)
- BZOJ1093 [ZJOI2007]最大半连通子图
- BZOJ1093: [ZJOI2007]最大半连通子图
- [bzoj1093][ZJOI2007]最大半连通子图
- BZOJ 1093: [ZJOI2007]最大半连通子图|tarjan|动态规划
- bzoj1093【ZJOI2007】最大半连通子图
- 【BZOJ 1093】 [ZJOI2007]最大半连通子图
- BZOJ 1093 ZJOI2007 最大半连通子图 Tarjan+动态规划
- bzoj 1093: [ZJOI2007]最大半连通子图
- BZOJ1093: [ZJOI2007]最大半连通子图
- BZOJ 1093 ZJOI 2007 最大半连通子图 强联通分量+拓扑图DP
- 【bzoj1093】 [ZJOI2007]最大半连通子图
- bzoj 1093 [ZJOI2007]最大半连通子图(scc+DP)
- BZOJ 1093 ZJOI 2007 最大半连通子图 DP
- BZOJ 1093 [ZJOI2007] 最大半连通子图(强联通缩点+DP)
- BZOJ 1093 [ZJOI2007]最大半连通子图
- 【bzoj 1093】: [ZJOI2007]最大半连通子图
- BZOJ1093 [ZJOI2007]最大半连通子图