洛谷 P4306 [JSOI2010]连通数 - 图论、统计
洛谷 P4306 [JSOI2010]连通数
算法标签: 图论
,统计
题目
题目描述
度量一个有向图联通情况的一个指标是连通数,指图中可达顶点对个的个数。
如图
顶点 1 可达 1, 2, 3, 4, 5
顶点 2 可达 2, 3, 4, 5
顶点 3 可达 3, 4, 5
顶点 4, 5 都只能到达自身。
所以这张图的连通数为 14。
给定一张图,请你求出它的连通数
输入格式
输入数据第一行是图顶点的数量,一个正整数N。 接下来N行,每行N个字符。第i行第j列的1表示顶点i到j有边,0则表示无边。
输出格式
输出一行一个整数,表示该图的连通数。
输入输出样例
输入 #1
3
010
001
100
输出 #1
9
说明/提示
对于100%的数据,N不超过2000。
题解:
某机房巨佬JZYshuraK_彧 推荐的题,貌似说有很多做法,不过作为一个蒟蒻,我搬出了许久没有用到的 毒瘤 SPFA,思路是将SPFA中的松弛更新最短路改为连通计数,最终统计\(ans\)即可。
大致实现如下(链式前向星存图):
void spfa(int s)
{
memset(vis, 0, sizeof vis);
queue <int> q;
q.push(s);
vis[s] = 1;
while(!q.empty())
{
int x, y;
x = q.front();
q.pop();
for (int i = head[x]; i; i = nex[i])
{
y = to[i];
if (!vis[y])
{
q.push(y);
vis[y] = 1;
ans ++ ;
}
}
}
}
之后按照操作统计答案即可,不过本题有毒瘤坑点。
本题坑点:
- 所读入矩阵之中没有空格,需要按照字符串读入在处理(被疯狂卡)
- 在输出的时候要记录\(ans + n\),原因在于这道题当中,自身与自身被算作连通,而在跑SPFA时候是没有记录自己的。
由于一个01串,假设为\(011111000001\) ,在这道题的题目下可以很简单的处理为\(0101\)这样一个串,在进行两种操作取最小值。
仔细分析这两种操作的时候,我们可以得到以下结论:
我们可以将所有中操作找出两种最优的:
- 将0放在一边,1放在一边,最终一次转换
- 每一个都单独转换
将字符串第0位设为一个1,这样我们只需要统计由某一位为0而前一位为1的个数,这样的答案就是操作的总次数(可以推得无论如何进行操作总次数都一致)。而且我们可以发现无论如何进行操作,最后一次都是转换,所以我们可以得出
\(ans = (cnt - 1) * min(x, y) + y;\)
由此此题得解,注意本题数据需要开long long
。
AC代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2020;
const int M = N * N;
int n, ans, vis[N];
int tot, to[M], nex[M], head[N];
void add(int x, int y)
{
to[++tot] = y;
nex[tot] = head[x];
head[x] = tot;
}
void spfa(int s)
{
memset(vis, 0, sizeof vis);
queue <int> q;
q.push(s);
vis[s] = 1;
while(!q.empty())
{
int x, y;
x = q.front();
q.pop();
for (int i = head[x]; i; i = nex[i])
{
y = to[i];
if (!vis[y])
{
q.push(y);
vis[y] = 1;
ans ++ ;
}
}
}
}
int main()
{
scanf("%d", &n);
char ch[2020];
for (int i = 1; i <= n; i ++ )
{
scanf("%s", ch + 1);
for (int j = 1; j <= n; j ++ )
{
if (ch[j] == '1')
add(i, j);
}
}
for (int i = 1; i <= n; i ++ )
spfa(i);
printf("%d", ans + n);
return 0;
}
原文地址:https://www.cnblogs.com/littleseven777/p/11851759.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 用SQL语句查看Oracle数据表的结构信息
- Oracle建表语法
- 剑指Offer第1题详解(附Java、Python实现代码)
- (美团)动态规划,打家劫舍!
- POIEasyExcel
- 剑指Offer第2题详解(附Python、Java代码实现)
- 剑指Offer第3题详解(附Java、Python源码)
- 从String中移除空白字符的多种方式!?差别竟然这么大!
- Stack.peek() 与 Stack.pop() 的区别
- 傅里叶变换有什么用?
- 剑指Offer第4题详解(附Java、Python源码)
- 帅地问我:Dubbo服务调用过程
- 用两个栈实现队列详解(附Java、Python源码)——《剑指Offer》
- PS2020制作电子签名
- 原创 | 险些翻车,差一点没做出来的基础算法题