Description

  一个有向图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的余数。

Input

  第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述接下来M行,每行两个正整
数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。N ≤1
00000, M ≤1000000;对于100%的数据, X ≤10^8

Output

  应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.

Sample Input

6 6 20070603
1 2
2 1
1 3
2 4
5 6
6 4

Sample Output

3
3
 
正解:tarjan+DP
解题报告:
  遥遥今天讲课讲了这道题,然后感觉这是最水的,就高兴地开了坑,调了半个晚上都没有发现为什么wa了。
  最后发现居然是有重边!!!!!!然后方案重复计算了,但我当时没有马上想出怎么判重,于是看了网上的题解发现可以用set,我真傻真的。
  做法其实挺简单,首先tarjan缩环,然后重构图,可以想到我们一定是在重构的图上选取一条链,使得链的点权和最大。DP可做。
 
 
 //It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#ifdef WIN32
#define OT "%I64d"
#else
#define OT "%lld"
#endif
using namespace std;
typedef long long LL;
const int MAXN = ;
const int MAXM = ;
int MOD;
int n,m,ecnt,ans,num;
int first[MAXN],to[MAXM],next[MAXM];
bool pd[MAXN];
int dfn[MAXN],low[MAXN];
int Stack[MAXN*],top,belong[MAXN];
int size[MAXN],cnt;
int head[MAXN],ru[MAXN],f[MAXN];
bool vis[MAXN]; set<pair<int,int> >bst;//要有一个空格 struct edge{
int v,next;
}e[MAXM]; inline int getint()
{
int w=,q=;
char c=getchar();
while((c<'' || c>'') && c!='-') c=getchar();
if (c=='-') q=, c=getchar();
while (c>='' && c<='') w=w*+c-'', c=getchar();
return q ? -w : w;
} inline void dfs(int x){
dfn[x]=++ecnt; low[x]=dfn[x];
pd[x]=; Stack[++top]=x;
for(int i=first[x];i;i=next[i]) {
int v=to[i];
if(!dfn[v]) { dfs(v); if(low[v]<low[x]) low[x]=low[v]; }
else if(pd[v]) low[x]=min(low[v],low[x]);
}
if(dfn[x]==low[x]){
cnt++; size[cnt]++; belong[x]=cnt; pd[x]=;
while(Stack[top]!=x&&top) belong[Stack[top]]=cnt,pd[Stack[top]]=,top--,size[cnt]++;
top--;
}
} inline void tarjan(){
ecnt=;
for(int i=;i<=n;i++) if(!dfn[i]) dfs(i);
ecnt=;
for(int i=;i<=n;i++) {
for(int j=first[i];j;j=next[j]) {
int v=to[j];
if(belong[i]!=belong[v]) {
if(bst.find(make_pair(belong[i],belong[v]))!=bst.end()) continue;
e[++ecnt].next=head[belong[i]]; head[belong[i]]=ecnt; e[ecnt].v=belong[v];
ru[belong[v]]++;
bst.insert(make_pair(belong[i],belong[v]));
}
}
}
} inline void DFS(int x){
vis[x]=;
for(int i=head[x];i;i=e[i].next) {
int v=e[i].v;
if(!vis[v]) DFS(v);
if(f[v]>f[x]) f[x]=f[v];
}
f[x]+=size[x];
} inline void DFS2(int x){
vis[x]=;
for(int i=head[x];i;i=e[i].next) {
int v=e[i].v;
if(!vis[v]) DFS2(v);
//不能有重边!!!!!!
if(f[x]==f[v]+size[x]) { dfn[x]+=dfn[v]; if(dfn[x]>=MOD) dfn[x]%=MOD; }
}
if(!head[x]) dfn[x]=;
if(f[x]==ans) { num+=dfn[x]; if(num>=MOD) num%=MOD; }
} inline void DP(){
memset(vis,,sizeof(vis));
for(int i=;i<=cnt;i++) if(!ru[i]) DFS(i),ans=max(ans,f[i]);
memset(vis,,sizeof(vis)); memset(dfn,,sizeof(dfn));
for(int i=;i<=cnt;i++)
if(!ru[i]) {
DFS2(i);
}
printf("%d\n%d",ans,num);
} inline void work(){
n=getint(); m=getint(); MOD=getint();
int x,y;
for(int i=;i<=m;i++) {
x=getint(); y=getint();
next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y;
}
tarjan();
DP();
} int main()
{
work();
return ;
}

BZOJ1093 最大半连通子图的更多相关文章

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

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

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

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

  3. 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 ...

  4. 【bzoj1093】[ZJOI2007]最大半连通子图 Tarjan+拓扑排序+dp

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

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

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

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

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

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

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

  8. 【bzoj1093】 [ZJOI2007]最大半连通子图

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

  9. 最大半连通子图 bzoj 1093

    最大半连通子图 (1.5s 128MB) semi [问题描述] 一个有向图G = (V,E)称为半连通的(Semi-Connected),如果满足:∀ u, v ∈V,满足u->v 或 v - ...

随机推荐

  1. FlashInspector 【Firefox浏览器插件,flash分析工具】

    Inspect flash(swf)'s DisplayObject with mouse. Overview the swf's DisplayObject list. Set the inspec ...

  2. LoadRunner参数化MySQL

    准备:安装[msql-ODBC驱动] 一.配置数据源 1.Win7,打开控制面板-系统和安全-管理工具,点击“数据源(ODBC)”. 打开数据源(ODBC),在用户DSN选项卡中点击“添加”按钮,弹出 ...

  3. IO流的练习1 —— 随机获取文本中的信息

    需求:一个文本中有几个名字,随机从中获取一个名字 分析: A:首先把文本中的数据读出 B:再把数据存储到集合中 C:产生一个随机的索引 D:打印出这个索引对应的值 public static void ...

  4. java7-4 继承的练习

    1.Override和Overload的区别,Overload能改变返回值类型吗? 答: Override就是方法重写:在子类中,出现和父类中一模一样的方法声明的现象 Overload就是方法重载:在 ...

  5. c++ web服务器

    https://github.com/facebook/proxygen http://tengine.taobao.org/ http://code.google.com/p/mongoose/ht ...

  6. 关于phpmyadmin #1045无法登陆服务器的问题

    修改/home/wwwroot/phpmyadmin/libraries/config.default.php 文件,找到下面两行 $cfg['Servers'][$i]['nopassword'] ...

  7. Power Builder的学习

    新的任务可能要运用PowerBuilder了,对这个名词之前仅是有所耳闻,工作中倒是用过power designer这个优秀的建模工具,出自同一家公司的产品,应该拥有同样的基因,于是上网开始查阅相关资 ...

  8. 在Function对象上扩展method方法

    ;(function() { /** * 在Function对象上扩展method方法 * @param {String} name 扩展的方法名称 * @param {Function} callb ...

  9. OSGEARTH三维地形开源项目

    第一章   OSGEarth介绍 第二章   OSGEarth编译环境配置 OSGEarth的编译环境配置随着版本的不同.运行平台的不同,也有很大的差异.本章主要以Windows XP SP3(x86 ...

  10. 【OpenGL】查看显卡对OpenGL的支持程度

    由于开发工作中要用到OpenGL的API进行渲染,公司配的电脑又是集成显卡,所以想知道显卡对OpenGL的支持程度. 下面介绍的方法就解决了这一点. 1.下载安装EVEREST Ultimate Ed ...