您的位置:首页 > 其它

【bzoj1093】【tarjan+dp】最大半联通子图

2016-12-26 22:08 337 查看
题意

导出子图:对图(U,V),有(U′,V′)满足 U′∈U V’是V中所有与U’相连的边

半连通子图:对图(U,V),对任意u∈U v∈U满足u到v或 v 到u 有一条有向路径

题解

首先考虑对于一个强连通分量一定是一个半连通导出子图,考虑缩点,对于缩点之后的DAG,在一条链上的强连通分量就为一个半联通子图,问题转化成求DAG最长链,考虑按拓扑序dp,记l[]为到该点的最长路径,记cnt[]为方案数,对于每个入度为0的点向其连通的点扩展

l[to]=l[u]+size[to](l[to]<l[u]+size[to])

cnt[to]+=cnt[u]



这题需要注意缩点之后的重边问题,记录vis为前驱标记,或者建图时优化。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#define MAXN 100001
using namespace std;
struct edge{
int to;
edge *nxt;
edge(){}
edge(int a):to(a),nxt(NULL){}
};
struct li{
edge *pre,*lst;
void push(int a){
if(!pre) pre=lst=new edge(a);
else lst=lst->nxt=new edge(a);
}
}e[MAXN],t[MAXN];
int n,m,X;
int bel[MAXN],dfn[MAXN],size[MAXN],low[MAXN],sta[MAXN],top,in[MAXN],P,T;
void tarjan(int u){
dfn[u]=low[u]=++T;sta[++top]=u;
for(edge *it=e[u].pre;it;it=it->nxt){
if(in[it->to]) continue;
if(!dfn[it->to]) tarjan(it->to);
low[u]=min(low[u],low[it->to]);
}
if(low[u]==dfn[u]){
int v;P++;
do{
size[P]++;
bel[v=sta[top--]]=P;in[v]=1;
}while(u!=v);
}
}
int l[MAXN],cnt[MAXN],ind[MAXN];
int vis[MAXN];
queue<int> q;
void Sort(){
memset(in,0,sizeof in);
for(int i=1;i<=P;i++)
if(ind[i]==0) l[i]=size[i],cnt[i]=1,q.push(i),in[i]=1;
while(!q.empty()){
int u=q.front();q.pop();
for(edge *it=t[u].pre;it;it=it->nxt){
if(ind[it->to]&&!in[it->to]){
ind[it->to]--;
if(ind[it->to]==0)
q.push(it->to),in[it->to]=1;
if(vis[it->to]==u) continue;
if(l[u]+size[it->to]>l[it->to]){
l[it->to]=l[u]+size[it->to];
cnt[it->to]=cnt[u];
}
else if(l[u]+size[it->to]==l[it->to])
cnt[it->to]=(cnt[it->to]+cnt[u])%X;
vis[it->to]=u;
}
}
}
}
int main(){
scanf("%d%d%d",&n,&m,&X);
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
e[a].push(b);
}
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;i++)
for(edge *it=e[i].pre;it;it=it->nxt)
if(bel[i]!=bel[it->to])
t[bel[i]].push(bel[it->to]),ind[bel[it->to]]++;
Sort();
int maxx=0,ans=0;
for(int i=1;i<=P;i++)
maxx=max(maxx,l[i]);
for(int i=1;i<=P;i++)
if(l[i]==maxx)
(ans+=cnt[i])%=X;
printf("%d\n%d\n",maxx,ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  bzoj tarjan