1093: [ZJOI2007]最大半连通子图

来源:互联网 发布:豆瓣fm windows客户端 编辑:程序博客网 时间:2024/04/29 07:49

无事闲来水一水Tarjan,结果水挂了。。。。。。

先Tarjan缩点。

第一问是DAG上的最长路径(点权)

第二问是最长路径的方案数。

都是DP。

然而第二问坑了。。。。。。

因为没判重边(很明显重新建图的时候会出现重边啊)

毕竟还是弱啊。

#include<iostream>#include<cstdio>#include<cstring>#include<stack>using namespace std;const int N=100000+5;const int M=1000000+5;typedef long long ll;inline int read(){int x=0;char ch;while(ch<'0'||ch>'9')ch=getchar();while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x;}struct Edge{int to,next;}e[M],g[M];int head[N],cnt,last[N];int val[N],sccno[N],scc_cnt;int pre[N],lowlink[N],dfs_clock;int d[N];ll f[N],mod;stack<int>s;int vis[N];void ins1(int u,int v){cnt++;e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt;}void ins2(int u,int v){cnt++;g[cnt].to=v;g[cnt].next=last[u];last[u]=cnt;}void tarjan(int u){pre[u]=lowlink[u]=++dfs_clock;s.push(u);for(int i=head[u];i;i=e[i].next){int v=e[i].to;if(!pre[v]){tarjan(v);lowlink[u]=min(lowlink[u],lowlink[v]);}else if(!sccno[v])lowlink[u]=min(lowlink[u],pre[v]);}if(lowlink[u]==pre[u]){scc_cnt++;while(true){int x=s.top();s.pop();sccno[x]=scc_cnt;val[scc_cnt]++;if(x==u)break;}}}int dp(int u){if(d[u])return d[u];d[u]=val[u];for(int i=last[u];i;i=g[i].next)d[u]=max(d[u],val[u]+dp(g[i].to));return d[u];}ll calc(int u){if(f[u])return f[u];int lim=0;for(int i=last[u];i;i=g[i].next)lim=max(lim,d[g[i].to]);for(int i=last[u];i;i=g[i].next)if(d[g[i].to]==lim){if(vis[g[i].to]==u)continue;vis[g[i].to]=u;f[u]=(f[u]+calc(g[i].to))%mod;}if(!f[u])f[u]=1;return f[u];}int main(){int n,m;n=read();m=read();mod=read();int u,v;while(m--){u=read();v=read();ins1(u,v);}for(int i=1;i<=n;i++)if(!pre[i])tarjan(i);cnt=0;for(int u=1;u<=n;u++)for(int i=head[u];i;i=e[i].next){int v=e[i].to;if(sccno[u]!=sccno[v])ins2(sccno[u],sccno[v]);}int ans=0;ll num=0;for(int i=1;i<=scc_cnt;i++)ans=max(ans,dp(i));printf("%d\n",ans);for(int i=1;i<=scc_cnt;i++)if(d[i]==ans)num=(num+calc(i))%mod;printf("%lld",num);return 0;}


0 0
原创粉丝点击