【问题描述】

没有环的有向图称为有向无环图,这是一个多么美好的结构吖。

如果有一张有 N 个点的有向图,我们可能需要删掉一些边使它变成一张有向无环图。假设初始时我们只有 N 个互不相连的点,当然它也是一张有向无环图。依次给出 T 条边和每条边的方向。 每给出一条边就要立即决定是否要加入这一条边,使得这张图始终是一张有向无环图(意思是:按顺序处理每条边,能加就加,让你模拟这个过程,自环不能加入)。计算在满足要求的情况下一共有多少条边没有被加入。如果所有边都可以加入这张图则输出 0。

【输入格式】

第一行为两个整数:N(1<=N<=250),T(0<=T<=100,000)。接下来 T 行,每行两个整数 x,y(1 <=x,y<= N),表示一条从 x 到 y 的单向边。

【输出格式】

一个整数,表示没有被加入的边数。

【样例输入】

3 6

1 2

1 3

3 1

2 1

1 2

2 3

【样例输出】

2

【样例说明】

1-->2,之前 2-->1 没有路径,不会造成环,加入

1-->3,之前 3-->1 没有路径,不会造成环,加入

3-->1,之前 1-->3 有路径,使得图有环,不加入

2-->1,之前 1-->2 有路径,不加入

1-->2 , 之前 2-->1 没有路径,加入

2-->3,之前 3-->2 没有路径,加入

因此答案是 2

【数据规模】

对于40%的数据,n<=50,T<=1000

对于90%的数据,n<=150,T<=100000

对于100%的数据,n<=250,T<=100000

题解

我们用\(f[i][j]\)表示\(i\)是否能到\(j\)(1:能 0:不能)。首先忽略重边。判断一条边能否加入显然是\(O(1)\)的,只要看看\(f[y][x]\)是不是\(1\)即可。

若加入,就要维护连通性。

如图,对于两个点\(A,B\),圈表示点集,箭头表示边,连边\(A\to B\)后我们又要连蓝边与绿边。

不难发现,我们可以把\(A\)与蓝色集合、\(B\)与绿色集合合并,于是问题就变成了:

蓝色集合向绿色集合连边。

蓝色集合为能到达\(A\)的点集;绿色集合表示能到达\(B\)的点集。

\(n^2\)大力连边即可。

我的代码

#include <cstring>
#include <fstream> using namespace std; ifstream fin("stock.in");
ofstream fout("stock.out"); const int maxm=100000;
const int maxn=256; int a[maxn][maxn];
int b[maxm],c[maxm]; int main()
{
int n, m;
fin >> n >> m;
int ans=0;
for(int i=0; i<m; ++i)
{
int aa, bb;
fin >> aa >> bb;
if(aa==bb || a[bb][aa]) ans++;
else
{
int k1=0;
int k2=0;
b[++k1]=aa;
c[++k2]=bb;
for(int j=1; j<=n; ++j)
if(a[j][aa] && !a[j][bb])
b[++k1]=j;
for(int j=1; j<=n; ++j)
if(a[bb][j] && !a[aa][j])
c[++k2]=j;
for(int j=1; j<=k1; ++j)
for(int k=1; k<=k2; ++k)
a[b[j]][c[k]]=1;
}
}
fout << ans << '\n';
return 0;
}

bitset优化

以上代码是可过的,但还可以用bitset优化一下,上一发zd大佬的代码。

#include <iostream>
#include <bitset>
#include <cstdio> using namespace std; typedef int ll; inline char gc()
{
static char buf[1<<14],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++;
} #define dd c=gc()
inline ll read()
{
ll x=0,f=1;
char dd;
for(; !isdigit(c); dd)if(c=='-')f=-1;
for(; isdigit(c); dd)x=(x<<1)+(x<<3)+(c^48);
return x*f;
}
#undef dd inline void write(ll x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10|48);
} bitset<252>a[252]; int main()
{
freopen("stock.in","r",stdin);
freopen("stock.out","w",stdout);
register ll n=read(),ans=0;
for (register ll i=0; i<n; ++i) a[i][i]=1;
for (register ll m=read(),x,y; m; --m)
{
x=read()-1,y=read()-1;
if (a[y][x]) ++ans;
else if (!a[x][y])
for (register ll i=0; i<n; ++i)
{
if (a[i][x]) a[i]=a[i]|a[y];
}
}
return write(ans),0;
}

20180429模拟赛T1——添边问题的更多相关文章

  1. 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解

    今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...

  2. 20180610模拟赛T1——脱离地牢

    Description 在一个神秘的国度里,年轻的王子Paris与美丽的公主Helen在一起过着幸福的生活.他们都随身带有一块带磁性的阴阳魔法石,身居地狱的魔王Satan早就想着得到这两块石头了,只要 ...

  3. NOIP欢乐模拟赛 T1 解题报告

    小澳的方阵 (matrix.cpp/c/pas) [题目描述] 小澳最近迷上了考古,他发现秦始皇的兵马俑布局十分有特点,热爱钻研的小澳打算在电脑上还原这个伟大的布局. 他努力钻研,发现秦始皇布置兵马俑 ...

  4. [模拟赛] T1 高级打字机

    Description 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧. 请为这种高级打字机设计一个程序,支持如下3种操作: 1.T x:在文章末尾打下一个小 ...

  5. 2019.2.25 模拟赛T1【集训队作业2018】小Z的礼物

    T1: [集训队作业2018]小Z的礼物 我们发现我们要求的是覆盖所有集合里的元素的期望时间. 设\(t_{i,j}\)表示第一次覆盖第i行第j列的格子的时间,我们要求的是\(max\{ALL\}\) ...

  6. [NOIP2018校模拟赛]T1 阶乘

    题目: 描述 有n个正整数a[i],设它们乘积为p,你可以给p乘上一个正整数q,使p*q刚好为正整数m的阶乘,求m的最小值. 输入 共两行. 第一行一个正整数n. 第二行n个正整数a[i]. 输出 共 ...

  7. [NOIP2018校模拟赛]T1聚会 party

    题目链接: 聚会 分析: 设每个点到1号点的距离为dist_{i},每个点的权值为x_{i},目标点到1号点的距离为dist,权值为x,那么对于每一次查询,我们讨论三种情况: ① 目标家庭在区间左边( ...

  8. 【2019.8.15 慈溪模拟赛 T1】插头(plugin)(二分+贪心)

    二分 首先,可以发现,最后的答案显然满足可二分性,因此我们可以二分答案. 然后,我们只要贪心,就可以验证了. 贪心 不难发现,肯定会优先选择能提供更多插座的排插,且在确定充电器个数的情况下,肯定选择能 ...

  9. 【2019.7.20 NOIP模拟赛 T1】A(A)(暴搜)

    打表+暴搜 这道题目,显然是需要打表的,不过打表的方式可以有很多. 我是打了两个表,分别表示每个数字所需的火柴棒根数以及从一个数字到另一个数字,除了需要去除或加入的火柴棒外,至少需要几根火柴棒. 然后 ...

随机推荐

  1. 屏蔽打开文件时提示“您尝试打开的文件xxx.xls的格式与文件扩展名指定的格式不一致。打开文件前请验证文件没有损坏且来源可信。是否立即打开该文 件?”

    修改注册表解决 1.打开注册表编辑器 方法:开始 -> 运行 -> 输入regedit -> 确定 2.找到注册表子项 HKEY_CURRENT_USER\Software\Micr ...

  2. kali 破解wifi

    1.查看网卡名称:iwconfig 有一块 名为wlan0 的无线网卡通过一下命令排除影响因素 root@jkali:~# iwconfig lo no wireless extensions. wl ...

  3. Selenium基础教程(三)自动化插件Katalon

    Katalon-一款好用的selenium自动化测试插件 Selenium 框架是目前使用较广泛的开源自动化框架,一款好的.基于界面的录制工具对于初学者来说可以快速入门:对于老手来说可以提高开发自动化 ...

  4. Springboot Actuator之八:actuator的执行原理

    本文接着<Springboot Actuator之七:actuator 中原生endpoint源码解析1>,前面主要分析了原生endpoint的作用. 现在着重了解actuator的执行原 ...

  5. Java随堂笔记一

    今天开始了Java的正式复习,因为有两三年没有接触Java了,所以打算开始从头复习. 下面使课堂的一些随堂笔记,如果有遗忘,我可以随时翻阅该博客. public static void main(St ...

  6. python环境安装及其就业状况

    一,下载及安装 1.进入官网下载 2.安装 二,就业前景 1.Python就业行情和前景分析之一 岗位数量 2..Python就业行情和前景分析之一 学历要求 3.工资状况

  7. java异常的嵌套和级联

    一.分开捕获或者嵌套使用 我们先看看下面这段代码: public class Cal { public int div(int a, int b) { int result = a / b; retu ...

  8. 示例:WPF中Slider控件封装的缓冲播放进度条控件

    原文:示例:WPF中Slider控件封装的缓冲播放进度条控件 一.目的:模仿播放器播放进度条,支持缓冲任务功能 二.进度: 实现类似播放器中带缓存的播放样式(播放区域.缓冲区域.全部区域等样式) 实现 ...

  9. C语言----循环结构1(基础篇五)

    今天更新一个C语言的循环,简单点就是就是我们平时在使用电脑时不停的刷新网页,生活中每天都要吃饭等等就是循环,而编程中也有不断循环的过程,或者遇到符合的条件结束循环 下面进入今天的主题: 需求:用计算机 ...

  10. 换个语言学一下 Golang (11)——使用包和测试

    Go天生就是为了支持良好的项目管理体验而设计的. 包 在软件工程的实践中,我们会遇到很多功能重复的代码,比如去除字符串首尾的空格.高质量软件产品的特点就是它的部分代码是可以重用的,比如你不必每次写个函 ...