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

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 100010
#define M 1000010
int n,m,P,p[N],p_new[N],dfn[N],low[N],stk[N],set[N],size[N],f[N],s[N],degree[N],q[N],top=,cnt=,t=,ans=;
bool flag[N];
vector<int> a[N];
struct data{int to,nxt;
}edge[M],edge_new[M];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void addedge_new(int x,int y){cnt++;edge_new[cnt].to=y,edge_new[cnt].nxt=p_new[x],p_new[x]=cnt;}
void tarjan(int k)
{
dfn[k]=low[k]=++cnt;
stk[++top]=k;flag[k]=;
for (int i=p[k];i;i=edge[i].nxt)
if (!dfn[edge[i].to]) tarjan(edge[i].to),low[k]=min(low[k],low[edge[i].to]);
else if (flag[edge[i].to]) low[k]=min(low[k],dfn[edge[i].to]);
if (dfn[k]==low[k])
{
t++;
while (stk[top]!=k)
{
size[t]++;
set[stk[top]]=t;
flag[stk[top]]=;
top--;
}
size[t]++;set[k]=t;flag[k]=;top--;
}
}
void topsort()
{
int head=,tail=;
for (int i=;i<=n;i++) if (!degree[i]) q[++tail]=i;
while (tail<n)
{
int x=q[++head];
for (int i=p[x];i;i=edge[i].nxt)
{
degree[edge[i].to]--;
if (!degree[edge[i].to]) q[++tail]=edge[i].to;
}
}
}
void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
int main()
{
freopen("bzoj1093.in","r",stdin);
freopen("bzoj1093.out","w",stdout);
n=read(),m=read(),P=read();
for (int i=;i<=m;i++)
{
int x=read(),y=read();
addedge(x,y);
}
t=;
for (int i=;i<=n;i++)
if (!dfn[i]) tarjan(i);
cnt=;
for (int i=;i<=n;i++)
for (int j=p[i];j;j=edge[j].nxt)
if (set[i]!=set[edge[j].to]) a[set[i]].push_back(set[edge[j].to]);
n=t;memset(flag,,sizeof(flag));
for (int i=;i<=n;i++)
{
int s=a[i].size();
for (int j=;j<s;j++)
if (!flag[a[i][j]]) addedge_new(i,a[i][j]),flag[a[i][j]]=,degree[a[i][j]]++;
for (int j=;j<s;j++)
flag[a[i][j]]=;
}
memcpy(p,p_new,sizeof(p));
memcpy(edge,edge_new,sizeof(edge));
topsort();
for (int v=n;v>=;v--)
{
int i=q[v];
s[i]=;
for (int j=p[i];j;j=edge[j].nxt)
if (f[edge[j].to]>f[i]) f[i]=f[edge[j].to],s[i]=s[edge[j].to];
else if (f[edge[j].to]==f[i]) inc(s[i],s[edge[j].to]);
f[i]+=size[i];
}
for (int i=;i<=n;i++) ans=max(ans,f[i]);
int tot=;
for (int i=;i<=n;i++) if (f[i]==ans) inc(tot,s[i]);
cout<<ans<<endl<<tot;
fclose(stdin);fclose(stdout);
return ;
}

BZOJ1093 ZJOI2007最大半连通子图(缩点+dp)的更多相关文章

  1. bzoj 1093 [ZJOI2007]最大半连通子图(scc+DP)

    1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 2286  Solved: 897[Submit][St ...

  2. bzoj1093: [ZJOI2007]最大半连通子图 scc缩点+dag上dp

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

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

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

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

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

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

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

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

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

  7. BZOJ1093: [ZJOI2007]最大半连通子图(tarjan dp)

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

  8. bzoj1093 [ZJOI2007]最大半联通子图 缩点 + 拓扑序

    最大半联通子图对应缩点后的$DAG$上的最长链 复杂度$O(n + m)$ #include <cstdio> #include <cstring> #include < ...

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

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

随机推荐

  1. 谈高清显示接口HDMI、RGB、LVDS、MIPI、eDP、mini-LVDS、V-By-One

    近年来随着电子产业的高速发展,智能显示设备也取得了辉煌的成就,高清显示得到了消费者的青睐.目前高清显示协议接口有RGB.LVDS.MIPI.eDP.HDMI.miniLVDS.V-by-One等,由于 ...

  2. CF809D Hitchhiking in the Baltic States LIS、平衡树

    传送门 看到最长上升子序列肯定是DP 设\(f_i\)表示计算到当前,长度为\(i\)的最长上升子序列的最后一项的最小值,显然\(f_i\)是一个单调递增的序列. 转移:对于当前计算的元素\(x\), ...

  3. 解决Oracle登录极慢的问题

    原文首发 http://anforen.com/wp/2018/04/oracle_login_slowly/ Oracle用PL/SQL登录,特别慢,3分钟以上,如果以前正常,并且按常见问题排查过, ...

  4. JavaScript 格式化数字 - 转

    function number_format(number, decimals, dec_point, thousands_sep,roundtag) { /* * 参数说明: * number:要格 ...

  5. [转]Linux下安装Java环境配置步骤详述

    1.下载jdk8 登录网址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 选择 ...

  6. Jquery的window.onload实现

    我们都知道jquery的$(document).ready(function(){});与window.onload不同,第一个是在DOM树构建完成后触发,第二个是页面完全加载后(包括图片等资源的加载 ...

  7. 基于Angular+WebAPI+OData的增删改查

    对于在ASP.NET WebAPI中怎么使用OData,已经在我前面的日志中的说明, 在ASP.NET Web API中使用OData 在这个示例中.我新建了一个Order的实体,在前端使用Angul ...

  8. [UWP 自定义控件]了解模板化控件(4):TemplatePart

    1. TemplatePart TemplatePart(部件)是指ControlTemplate中的命名元素.控件逻辑预期这些部分存在于ControlTemplate中,并且使用protected ...

  9. 《Linux内核设计与实现》第三章读书笔记

    一.进程(任务)描述 1.进程是处于执行期的程序:除了可执行程序代码,还包括打开的文件.挂起的信号.内核内部数据.一个或者多个执行线程等多种资源 线程是在进程活动中的对象:内核调度的对象是线程而不是进 ...

  10. Linux内核分析——第五章 系统调用

    第五章 系统调用 5.1 与内核通信 1.系统调用在用户空间进程和硬件设备之间添加了一个中间层,该层主要作用有三个: (1)为用户空间提供了一种硬件的抽象接口 (2)系统调用保证了系统的稳定和安全 ( ...