# BZOJ 1093 ZJOI 2007 最大半连通子图 强联通分量+拓扑图DP

Tarjan 专栏收录该内容
2 篇文章 0 订阅

1.最大半连通子图的大小
2.最大半连通子图的个数

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
typedef long long ll;
{
char ls=getchar(),k=0;for(;ls<'0'||ls>'9';k=ls,ls=getchar());
ll x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0';
if(k=='-')x=-x;return x;
}

stack<ll>zhan;
ll edge[1000005];
ll z[1000005];

ll last[100005];
ll low[100005];
ll dfn[100005];
ll pzhan[100005];
ll visit[100005];

ll mod;
ll n,m;
ll s;
////////////////////////
ll n2;
ll ji;
ll goal[100005];
ll dj[100005];
ll zhi[100005];
ll back[100005];
///////////////////////
ll ji2;
ll edge2[1000005];
ll z2[1000005];
ll last2[100005];
ll dq[100005];
ll rd[100005];
ll kp[100005];
ll sign;
////////////////////////
ll edge3[1000005];
ll z3[1000005];
ll last3[100005];
/////////////////////
ll maxn;
ll sum;
ll zl[100005];
ll maxx;
ll summ;
ll pd[100005];

inline void tarjan(ll d)//强连通分量
{
dfn[d]=low[d]=++s;
zhan.push(d);pzhan[d]=1;visit[d]=1;
for(ll k=last[d];k!=0;k=z[k])
{
ll v=edge[k];
if(visit[v]==0)
{
tarjan(v);
low[d]=min(low[d],low[v]);
}
else if(pzhan[v]==1)
{
low[d]=min(low[d],dfn[v]);
}
}
if(dfn[d]==low[d])//规划旧点集和新点集
{
++n2;
ll g=zhan.top();
while(dfn[g]!=low[g])
{
++dq[n2];
goal[g]=n2;
dj[++ji]=g;
zhi[ji]=back[n2];
back[n2]=ji;
pzhan[g]=0;
zhan.pop();
g=zhan.top();
}
++dq[n2];
goal[g]=n2;
dj[++ji]=g;
zhi[ji]=back[n2];
back[n2]=ji;
pzhan[g]=0;zhan.pop();
}
return;
}

void kpsort()//拓扑排序
{
for(int i=1;i<=n2;++i)
{
ll d=kp[i];
for(int k=last3[d];k!=0;k=z3[k])
{
ll v=edge3[k];
--rd[v];
if(rd[v]==0)
kp[++sign]=v;
}
}
return;
}

void dp()//拓扑图动态规划
{
for(int i=1;i<=n2;++i)
{
ll d=kp[i];
maxx=0;
summ=1;
for(int k=last2[d];k!=0;k=z2[k])
{
ll v=edge2[k];
if(dq[v]==maxx)
{
summ+=zl[v];
summ=summ%mod;
}
else if(dq[v]>maxx)
{
maxx=dq[v];
summ=zl[v];
}
}
dq[d]+=maxx;
zl[d]=summ;
if(dq[d]==maxn)
{
sum+=zl[d];
sum=sum%mod;
}
else if(dq[d]>maxn)
{
maxn=dq[d];
sum=zl[d];
}
}
return;
}

int main()
{
for(int i=1;i<=m;++i)
{
edge[i]=b1;
z[i]=last[a1];
last[a1]=i;
}

for(int i=1;i<=n;++i)
{
if(visit[i]==0)
tarjan(i);
}

for(int i=1;i<=n2;++i)//建立新图的边
{
for(int k=back[i];k!=0;k=zhi[k])
{
ll v=dj[k];
for(int kk=last[v];kk!=0;kk=z[kk])
{
ll u=edge[kk];
ll gs=goal[u];
if(gs!=i&&pd[gs]!=i)
{
pd[gs]=i;
++rd[gs];
edge2[++ji2]=i;//统计一个点的出边（拓扑排序用）
z2[ji2]=last2[gs];
last2[gs]=ji2;
edge3[ji2]=gs;//统计一个点的入边（动态规划用）
z3[ji2]=last3[i];
last3[i]=ji2;
}
}
}
}

for(int i=1;i<=n2;++i)//将入度为0的点进入拓扑序列
{
if(rd[i]==0)
{
zl[i]=1;
kp[++sign]=i;
}
}
kpsort();//拓扑排序
dp();//动态规划
cout<<maxn<<endl<<sum<<endl;
return 0;
}
• 0
点赞
• 0
评论
• 0
收藏
• 一键三连
• 扫一扫，分享海报

04-24 182
07-10 358

07-12 320
09-13 984
02-22 510
04-22 666
08-31 941
07-04 192
03-29 574
09-17
09-18
05-23 8279