一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意
两点u,v,存在一条u到v的有向路径或者从v到u的有向路径。若G'=(V',E')满足V'?V,E'是E中所有跟V'有关的边,
则称G'是G的一个导出子图。若G'是G的导出子图,且G'半连通,则称G'为G的半连通子图。若G'是G所有半连通子图
中包含节点数最多的,则称G'是G的最大半连通子图。给定一个有向图G,请求出G的最大半连通子图拥有的节点数K
,以及不同的最大半连通子图的数目C。由于C可能比较大,仅要求输出C对X的余数。

解法:把scc缩点,同一个连通分量里肯定互相可达,然后变成了dag,只需要跑一个dag上dp找最长路即可,然后需要记录一下最长路方案数,需要注意的确定点之后边就确定了,所以scc缩点时需要判一下重边

/**************************************************************
Problem: 1093
User: walfy
Language: C++
Result: Accepted
Time:4788 ms
Memory:49420 kb
****************************************************************/ //#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-;
const int N=+,maxn=+,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; int n,m,X;
stack<int>s;
vector<int>v[N],vv[N],ans[N];
int dfn[N],low[N];
int ins[N],inans[N];
int num,ind;
int a[maxn],b[maxn];
void tarjan(int u)
{
ins[u]=;
low[u]=dfn[u]=++ind;
s.push(u);
for(int i=;i<v[u].size();i++)
{
int t=v[u][i];
if(dfn[t]==)
{
tarjan(t);
low[u]=min(low[u],low[t]);
}
else if(ins[t]==)low[u]=min(low[u],dfn[t]);
}
if(low[u]==dfn[u])
{
++num;
while(!s.empty()){
int k=s.top();
s.pop();
ins[k]=;
ans[num].push_back(k);
inans[k]=num;
if(k==u)break;
}
}
}
map<pii,int>ma;
void scc()
{
for(int i=;i<=n;i++)
if(!dfn[i])
tarjan(i);
for(int i=;i<m;i++)
{
int x=inans[a[i]],y=inans[b[i]];
if(x!=y&&!ma[mp(x,y)])vv[x].pb(y),ma[mp(x,y)]=;
}
}
pii dp[N];
pii DP(int u)
{
if(dp[u].fi!=-)return dp[u];
dp[u].fi=ans[u].size(),dp[u].se=;
for(int i=;i<vv[u].size();i++)
{
int x=vv[u][i];pii te=DP(x);
if(dp[u].fi<te.fi+ans[u].size())
{
dp[u]=te,dp[u].fi=te.fi+ans[u].size();
// printf("%d %d %d %d\n",u,x,dp[u].fi,dp[u].se);
}
else if(dp[u].fi==te.fi+ans[u].size())
{
dp[u].se=(dp[u].se+te.se)%X;
// printf("%d %d %d +++%d\n",u,x,dp[u].se,te.se);
}
}
return dp[u];
}
int main()
{
scanf("%d%d%d",&n,&m,&X);
for(int i=;i<m;i++)
{
scanf("%d%d",&a[i],&b[i]);
v[a[i]].pb(b[i]);
}
scc();
memset(dp,-,sizeof dp);
for(int i=;i<=n;i++)
DP(i);
int ma=;
for(int i=;i<=num;i++)ma=max(ma,dp[i].fi);//,printf("%d %d\n",dp[i].fi,dp[i].se);
int ans=;
for(int i=;i<=num;i++)if(dp[i].fi==ma)ans=(ans+dp[i].se)%X;
printf("%d\n%d\n",ma,ans);
return ;
}
/*********************** ***********************/

bzoj1093: [ZJOI2007]最大半连通子图 scc缩点+dag上dp的更多相关文章

  1. BZOJ1093 ZJOI2007最大半连通子图(缩点+dp)

    发现所谓半连通子图就是缩点后的一条链之后就是个模板题了.注意缩点后的重边.写了1h+真是没什么救了. #include<iostream> #include<cstdio> # ...

  2. [luogu2272 ZJOI2007] 最大半连通子图 (tarjan缩点 拓扑排序 dp)

    传送门 题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向 ...

  3. [ZJOI2007]最大半连通子图 (Tarjan缩点,拓扑排序,DP)

    题目链接 Solution 大概是个裸题. 可以考虑到,如果原图是一个有向无环图,那么其最大半联通子图就是最长的一条路. 于是直接 \(Tarjan\) 缩完点之后跑拓扑序 DP就好了. 同时由于是拓 ...

  4. 2018.11.06 bzoj1093: [ZJOI2007]最大半连通子图(缩点+拓扑排序)

    传送门 先将原图缩点,缩掉之后的点权就是连通块大小. 然后用拓扑排序统计最长链数就行了. 自己yyyyyy了一下一个好一点的统计方法. 把所有缩了之后的点都连向一个虚点. 然后再跑拓扑,这样最后虚点的 ...

  5. [ZJOI2007]最大半连通子图(Tarjan,拓扑序DP)

    [ZJOI2007]最大半连通子图 题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v ...

  6. BZOJ1093 [ZJOI2007]最大半连通子图 【tarjan缩点 + DAG最长路计数】

    题目 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意 两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G ...

  7. BZOJ1093 [ZJOI2007]最大半连通子图

    Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u ...

  8. bzoj1093[ZJOI2007]最大半连通子图(tarjan+拓扑排序+dp)

    Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u ...

  9. 【tarjan 拓扑排序 dp】bzoj1093: [ZJOI2007]最大半连通子图

    思维难度不大,关键考代码实现能力.一些细节还是很妙的. Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于 ...

随机推荐

  1. centos7提示ifconfig command not found解决

    安装centos7时,选择了minimal install的话,没有安装网络组件. yum install net-tools 可以解决问题.

  2. 【MYSQL】主从常见问题运维

    参见Mysql主从常见错误,http://hzcsky.blog.51cto.com/1560073/479476

  3. 使用stringstream格式化字符串

    stringstream所在头文件为<sstream> 一般有如下常用功能: 1.安全格式化字符串 stringstream常用来安全的格式化若干个字符串,数值到一个缓冲区, 而不用担心溢 ...

  4. 成员函数查找[条款24]---《C++必知必会》

    调用一个成员函数,涉及三个步骤:第一步,编译器查找函数的名字:第二部,从可用候选者中选择最佳匹配函数:第三步,检查是否具有访问该函数的权限. #include<iostream> usin ...

  5. C语言赋初始值

  6. javascript 类型 内存 对象

    var box =0 function test() { alert(box) //全局 }

  7. Winter-1-E Let the Balloon Rise 解题报告及测试数据

    Time Limit:1000MS     Memory Limit:32768KB Description Contest time again! How excited it is to see ...

  8. java 2017/6/26杂记

    mkdirs()可以建立多级文件夹, mkdir()只会建立一级的文件夹, 如下: new File("/tmp/one/two/three").mkdirs(); 执行后, 会建 ...

  9. 20145312 《Java程序设计》第六周学习总结

    20145312 <Java程序设计>第六周学习总结 学习笔记 Chapter10 输入 /输出 10.1InputStream 与 OutputStream 10.1.1 串流设计的概念 ...

  10. SpringMVC对于传入多个对象参数遇到的问题

    最近遇到一个问题,一个添加接口,需要添加三个对象,而且这三个对象里面的属性名很多都是一样的,本来是拿三个对象直接接收值,但是因为很多属性名都一样,所以接收不到值.百度也有的说把这三个对象的参数重命名然 ...