HDU 4635 Strongly connected ——(强连通分量)
好久没写tarjan了,写起来有点手生,还好1A了- -。
题意:给定一个有向图,问最多添加多少条边,让它依然不是强连通图。
分析:不妨考虑最大时候的临界状态(即再添加一条边就是强连通图的状态),假设这时候的边的数量是F,那么答案就是F-m(m是一开始边的数量)。因此,F越大,答案越大。那么,怎么考虑F的值呢?最后的状态一定是这样的:整个图不是强连通的,但是他的两个分部x和y都是强连通的,并且其中任意一个分量(不妨设其为x),到另外一个分量(y),x中的每一个点到y中的每一个点都有边,而且,y中的每一个点到x中的每一个点都没有边;另外,x和y内部任意两点间都是有边的。这样的话任意添加一条边都会使得原图变成一个强连通图(因为再添加边只能是y中一点到x一点,这样整个图中任意两点间都可达了)。那么我们不妨设x中点的个数为a,y中点的个数为b=n-a(共有n个点),因此F=a*(a-1)+b*(b-1)+a*b(x到y的边)。这样,ans=F-m,化简得到ans=n*n-a*b-n-m。对a和b进行基本不等式可知,他们相等时乘积最大,因此他们相差最大时ans最大(也可以直接枚举任意两个强连通分量来得到答案)。另外要注意的一点是,x和y必须一个有任意一个是入度或者出度为0的,这样的话,才能使得他们构造成为F的状态。还想提的一点是,一个点也能成为强连通分量。
具体见代码:
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <stack>
using namespace std;
const int inf = 0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int> pii;
const int N = + ; int n,m,dfs_clock,dfn[N],low[N];
int belong[N],scc_cnt,cnt[N],in[N],out[N];
stack<int> S;
vector<int> G[N]; void init()
{
for(int i=;i<=n;i++) G[i].clear();
dfs_clock = ;
memset(dfn,,sizeof(dfn));
memset(belong,,sizeof(belong));
scc_cnt = ;
memset(cnt,,sizeof(cnt));
memset(in,,sizeof(in));
memset(out,,sizeof(out));
} void tarjan(int u)
{
dfn[u]=low[u]=++dfs_clock;
S.push(u);
for(int i=;i<G[u].size();i++)
{
int v = G[u][i];
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(!belong[v])
{
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u])
{
scc_cnt++;
int num = ;
for(;;)
{
num ++;
int x = S.top();S.pop();
belong[x] = scc_cnt;
if(x==u) break;
}
cnt[scc_cnt] = num;
}
} void solve()
{
for(int i=;i<=n;i++)
{
if(!dfn[i]) tarjan(i);
} for(int i=;i<=n;i++)
{
int x = belong[i];
for(int j=;j<G[i].size();j++)
{
int v = G[i][j];
if(belong[i] == belong[v]) continue; int y = belong[v];
out[x]++;
in[y]++;
}
} ll ans = ;
for(int i=;i<=scc_cnt;i++)
{
if(in[i] && out[i]) continue; int a = cnt[i];
int b = n-a;
ans = max(ans,(ll)n*n-(ll)a*b-n-m);
}
if(scc_cnt == ) ans = -;
cout << ans << endl;
} int main()
{
int T;
scanf("%d",&T);
for(int kase=;kase<=T;kase++)
{
init();
printf("Case %d: ",kase);
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
}
solve();
}
}
HDU 4635 Strongly connected ——(强连通分量)的更多相关文章
- HDU 4635 Strongly connected (强连通分量)
题意 给定一个N个点M条边的简单图,求最多能加几条边,使得这个图仍然不是一个强连通图. 思路 2013多校第四场1004题.和官方题解思路一样,就直接贴了~ 最终添加完边的图,肯定可以分成两个部X和Y ...
- HDU 4635 Strongly connected (强连通分量+缩点)
<题目链接> 题目大意: 给你一张有向图,问在保证该图不能成为强连通图的条件下,最多能够添加几条有向边. 解题分析: 我们从反面思考,在该图是一张有向完全图的情况下,最少删去几条边能够使其 ...
- hdu 4635 Strongly connected 强连通缩点
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4635 题意:给你一个n个点m条边的图,问在图不是强连通图的情况下,最多可以向图中添多少条边,若图为原来 ...
- HDU 4635 Strongly connected(强连通)经典
Strongly connected Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- hdu 4635 Strongly connected 强连通
题目链接 给一个有向图, 问你最多可以加多少条边, 使得加完边后的图不是一个强连通图. 只做过加多少条边变成强连通的, 一下子就懵逼了 我们可以反过来想. 最后的图不是强连通, 那么我们一定可以将它分 ...
- HDU 4635 Strongly connected (2013多校4 1004 有向图的强连通分量)
Strongly connected Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- HDU 4635 Strongly connected(强连通分量,变形)
题意:给出一个有向图(不一定连通),问最多可添加多少条边而该图仍然没有强连通. 思路: 强连通分量必须先求出,每个强连通分量包含有几个点也需要知道,每个点只会属于1个强连通分量. 在使图不强连通的前提 ...
- HDU 4635 - Strongly connected(2013MUTC4-1004)(强连通分量)
t这道题在我们队属于我的范畴,最终因为最后一个环节想错了,也没搞出来 题解是这么说的: 最终添加完边的图,肯定可以分成两个部X和Y,其中只有X到Y的边没有Y到X的边,那么要使得边数尽可能的多,则X部肯 ...
- HDU 4635 —— Strongly connected——————【 强连通、最多加多少边仍不强连通】
Strongly connected Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u ...
随机推荐
- 数据库优化方案之SQL脚本优化
随着数据库数据越来越大,数据单表存在的数据量也就随之上去了,那么怎么样让我们的脚本查询数据更快呢? 在这个地方我们主要提到两个数据库类型: 1.MSSQL(该数据库我们通过执行计划来查看数据库性能在哪 ...
- List和Dictionary互转
// 声明Dictionary并初始化 Dictionary<string, string> dic = new Dictionary<string, string>() { ...
- aspectcore 简单解析
.netcore 下aspectcore 的使用 动态代理: static void Main(string[] args) { Console.WriteLine("Hello Worl ...
- docker启动 elasticsearch 修改 xmx xms 堆内存大小修改
用docker 安装的elasticsearch 5.6版本默认堆内存最大设置的2G 可以通过如下方法修改 [root@nova-92 logs]# find /var/lib/docker/ -na ...
- Miniconda虚拟环境管理工具命令方法
创建制定Python版本的虚拟环境 conda create --name 虚拟环境名称 Python=3.7.3(版本号) 进入指定虚拟环境 conda activate 虚拟环境名称 退出虚拟环境 ...
- Jupyter安装和环境配置
配置: 1. 命令行启动 jupyter notebook 2. 也可以Anaconda直接启动 3. 设置token,如下图所示,命令行中输入 jupyter notebook list C:\Us ...
- (十三)r18 cpu id
1.cpuid内核接口 lichee/linux-4.4/drivers/soc/sunxi/sunxi-sid.c int sunxi_get_soc_chipid(u8 *chipid) int ...
- Linux学习笔记(三)Linux常用命令:链接命令和文件查找命令
一.链接命令 ln -s [原文件] [目标文件] (link) -s意为创建软连接 硬链接和软连接 硬链接的特点: (1)拥有相同的 i 结点和block块,可以看作是同一个文件 (2)可以通过 i ...
- idou老师教你学Istio 04:Istio性能及扩展性介绍
Istio的性能问题一直是国内外相关厂商关注的重点,Istio对于数据面应用请求时延的影响更是备受关注,而以现在Istio官方与相关厂商的性能测试结果来看,四位数的qps显然远远不能满足应用于生产的要 ...
- 说一下 HashMap 的实现原理?(未完成)
说一下 HashMap 的实现原理?(未完成)