P2272 [ZJOI2007]最大半连通子图
思路
tarjan的题目
注意是要选出一个点集而不是边集
第一问就是缩点之后最长链,第二问就是有多少个最长链,注意缩点后连边要去重(不然一个链的方案可能会被统计多次)
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include <set>
using namespace std;
int scc_cnt,sccno[100100],sccnum[100100],low[100100],dfn[100100],vis[100100],vis2[100100],dp1[100100],dfs_clock,n,m,MOD;
pair<int,int> dp2[100100];
struct Graph{
    int u[1001000],v[1001000],fir[1001000],nxt[1001000],cnt=0;
    void addedge(int ui,int vi){
        ++cnt;
        u[cnt]=ui;
        v[cnt]=vi;
        nxt[cnt]=fir[ui];
        fir[ui]=cnt;
    }
}G1,G2;
stack<int> S;
set<pair<int,int> > S2;
void tarjan(int u){
    low[u]=dfn[u]=++dfs_clock;
    S.push(u);
    vis[u]=true;
    for(int i=G1.fir[u];i;i=G1.nxt[i]){
        if(!dfn[G1.v[i]]){
            tarjan(G1.v[i]);
            low[u]=min(low[u],low[G1.v[i]]);
        }
        else if(vis[G1.v[i]])
            low[u]=min(low[u],low[G1.v[i]]);
    }
    if(dfn[u]==low[u]){
        scc_cnt++;
        while(1){
            int x=S.top();
            S.pop();
            vis[x]=false;
            sccno[x]=scc_cnt;
            if(x==u)
                break;
        }
    }
}
void sd(void){
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            tarjan(i);
    for(int i=1;i<=n;i++){
        sccnum[sccno[i]]++;
        for(int j=G1.fir[i];j;j=G1.nxt[j]){
            int u=sccno[i],v=sccno[G1.v[j]];
            if(u>v)
                swap(u,v);
            if(S2.count(make_pair(u,v)))
                continue;
            S2.insert(make_pair(u,v));
            if(sccno[i]!=sccno[G1.v[j]])
                G2.addedge(sccno[i],sccno[G1.v[j]]);
            }
        }
}
int dfs1(int x){
    if(vis[x])
        return dp1[x];
    vis[x]=true;
    for(int i=G2.fir[x];i;i=G2.nxt[i]){
        dp1[x]=max(dfs1(G2.v[i]),dp1[x]);
    }
    dp1[x]+=sccnum[x];
    return dp1[x];
}
pair<int,int> dfs2(int x){
    if(vis2[x])
        return dp2[x];
    vis2[x]=true;
    dp2[x]=make_pair(0,1);
    for(int i=G2.fir[x];i;i=G2.nxt[i]){
        pair<int,int> t=dfs2(G2.v[i]);
        if(t.first>dp2[x].first){
            dp2[x]=t;
        }
        else if(t.first==dp2[x].first){
            dp2[x].second=(dp2[x].second+t.second)%MOD;
        }
    }
    dp2[x].first+=sccnum[x];
    return dp2[x];
}
int main(){
    scanf("%d %d %d",&n,&m,&MOD);
    for(int i=1;i<=m;i++){
        int a,b;
        scanf("%d %d",&a,&b);
        G1.addedge(a,b);
    }
    sd();
    int ans=0,ans2=0;
    for(int i=1;i<=scc_cnt;i++)
        ans=max(ans,dfs1(i));
    for(int i=1;i<=scc_cnt;i++){
        pair<int,int> t=dfs2(i);
        if(t.first==ans)
            ans2=(ans2+t.second)%MOD;
    }
    printf("%d\n%d\n",ans,ans2);
    return 0;
}
P2272 [ZJOI2007]最大半连通子图的更多相关文章
- 洛谷 P2272 [ZJOI2007]最大半连通子图 解题报告
		P2272 [ZJOI2007]最大半连通子图 题目描述 一个有向图\(G=(V,E)\)称为半连通的\((Semi-Connected)\),如果满足:\(\forall u,v \in V\),满 ... 
- Luogu P2272 [ZJOI2007]最大半连通子图(Tarjan+dp)
		P2272 [ZJOI2007]最大半连通子图 题意 题目描述 一个有向图\(G=(V,E)\)称为半连通的\((Semi-Connected)\),如果满足:\(\forall u,v\in V\) ... 
- luogu P2272 [ZJOI2007]最大半连通子图
		题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若 ... 
- P2272 [ZJOI2007]最大半连通子图 tarjan+DP
		思路:$tarjan+DP$ 提交:1次 题解:首先对于一个强连通分量一定是一个半连通分量,并且形成的半连通分量的大小一定是它的$size$,所以我们先缩点. 这样,我们相当于要在新的$DAG$上找一 ... 
- 题解 P2272 【[ZJOI2007]最大半连通子图】
		P2272 [ZJOI2007]最大半连通子图 萌新初学Tarjan,在<信息学奥赛一本通-提高篇>中看到这题,看到题解不多,便想发布一篇较为清新简洁的题解.--第5道紫题 题目大意: 定 ... 
- BZOJ 1093 [ZJOI2007] 最大半连通子图(强联通缩点+DP)
		题目大意 题目是图片形式的,就简要说下题意算了 一个有向图 G=(V, E) 称为半连通的(Semi-Connected),如果满足图中任意两点 u v,存在一条从 u 到 v 的路径或者从 v 到 ... 
- BZOJ 1093 [ZJOI2007]最大半连通子图
		1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 1986 Solved: 802[Submit][St ... 
- bzoj 1093 [ZJOI2007]最大半连通子图(scc+DP)
		1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 2286 Solved: 897[Submit][St ... 
- BZOJ 1093: [ZJOI2007]最大半连通子图( tarjan + dp )
		WA了好多次... 先tarjan缩点, 然后题意就是求DAG上的一条最长链. dp(u) = max{dp(v)} + totu, edge(u,v)存在. totu是scc(u)的结点数. 其实就 ... 
随机推荐
- Life Winner Bo (博弈论)
			kind:维持让对手处于(奇数,奇数)的状态,就能赢. rook:维持让对手处于(A,A)相等的状态,就能赢. knight:画图找规律,没有到达终点的就是平局. queen:威佐夫博弈论,终点不一样 ... 
- codeforces 980A Links and Pearls
			题意: 有珍珠和线,问能否重新安排使得相邻珍珠之间的线的数量相等. 思路: 首先,珍珠为0或者线为0,那么都满足条件: 其次,如果珍珠的个数大于线的个数,那么肯定不满足条件: 然后,如果线的个数能够被 ... 
- OpenCV LK光流法测试
			OpenCV版本: 3.2.0 例程文件目录/samples/cpp/lkdemo.cpp 原始程序是采集相机数据,台式机没有摄像头,用Euroc测试集,偷ORB_SLAM2 /Examples/Mo ... 
- arm cortex-m0plus源码学习(三)GPIO
			概述: Cortex-m0的integration_kit提供三个GPIO接口,其中GPIO0传输到外部供用户使用,为EXTGPIO:GPIO1是内核自己的信号,不能乱改,会崩掉:GPIO2是一些中断 ... 
- RocketMQ 问题汇总
			1. rocketMQ安装: 编译完成以后准备启动项目,注意:bin的位置是编译后target目录下,启动命令在这里. linux命令目录:你的目录/rocketmq-all-4.2.0/distri ... 
- 关于reduce输出write方法
			关于hadoop一些自定义输出 code>OutputFormat</code> describes the output-specification for a * Map-Red ... 
- Centos7升级gcc学习笔记  gcc 4.8.5 -> gcc 5.4.0
			摘自:https://www.cnblogs.com/highway-9/p/5628852.html 一.安装开发必备环境: yum groupinstall "Development T ... 
- Java常考面试题(一)
			https://blog.csdn.net/linzhiqiang0316/article/details/80473906 
- iOS项目之报错笔记
			问题一: linker command failed with exit code 1 (use -vto see invocation) 原因:导入了.m的头文件,导致同时有两个一样的.m文件在编译 ... 
- Mongo第三个参数的用法
			Mongo update的用法 Update( array $criteria , array $new_object [, array $options = array() ] ) 第一个参数是条件 ... 
