hust 1260 Dominos && hust 1516 Dominos

题目描述

Dominos are lots of fun. Children like to stand the tiles on their side in
long lines. When one domino falls, it knocks down the next one, which knocks
down the one after that, all the way down the line. However, sometimes a domino
fails to knock the next one down. In that case, we have to knock it down by hand
to get the dominos falling again.

Your task is to determine, given the
layout of some domino tiles, the minimum number of dominos that must be knocked
down by hand in order for all of the dominos to fall.

输入

The first line of input contains one integer specifying the number of test
cases to follow. Each test case begins with a line containing two integers, each
no larger than 100 000. The first integer n is the number of
domino tiles and the second integer m is the number of lines
to follow in the test case. The domino tiles are numbered from 1
to n. Each of the following lines contains two
integers x and y indicating that if domino
number x falls, it will cause domino
number y to fall as well.

输出

For each test case, output a line containing one integer, the minimum number
of dominos that must be knocked over by hand in order for all the dominos to
fall.

样例输入

1
3 2
1 2
2 3

样例输出

1

这个题怎么看都觉得是一个水题,只要找入度为0的点不就是吗?当然是了,入度为0的点肯定对的,但是考虑一下,若1-〉2,2-〉1,那么入度为0 的点为0个,但是答案肯定为1,为什么呢,因为出现了环,所以我们要不环去掉,就是要缩点,当然是强连通分量来做,


#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define inf 0x0f0f0f0f
using namespace std;

int indegree[100000+10];

struct SCC
{
static const int maxn=100000+10;
vector<int>group[maxn],scc[maxn];
int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt,n,m;
stack<int>S;

void init()
{
for (int i=0;i<=n;i++) group[i].clear();
}

void addedge(int from,int to)
{
group[from].push_back(to);
}

void dfs(int u)
{
pre[u]=lowlink[u]=++dfs_clock;
S.push(u);
for (int i=0;i<group[u].size();i++)
{
int v=group[u][i];
if (!pre[v])
{
dfs(v);
lowlink[u]=min(lowlink[u],lowlink[v]);
}
else if (!sccno[v])
{
lowlink[u]=min(lowlink[u],pre[v]);
}
}
if (lowlink[u]==pre[u])
{
scc_cnt++;
scc[scc_cnt].clear();
while (1)
{
int x=S.top();
S.pop();
scc[scc_cnt].push_back(x);
sccno[x]=scc_cnt;
if (x==u) break;
}
}
}

void find_scc()
{
dfs_clock=scc_cnt=0;
memset(pre,0,sizeof(pre));
memset(sccno,0,sizeof(sccno));
for (int i=1;i<=n;i++)
if (!pre[i]) dfs(i);
}
};

SCC Dominos;

int main()
{
int x,y,M,T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&Dominos.n,&Dominos.m);
Dominos.init();
M=Dominos.m;
while(M--)
{
scanf("%d%d",&x,&y);
Dominos.addedge(x,y);
}
Dominos.find_scc();
for (int i=1;i<=Dominos.scc_cnt;i++) indegree[i]=0;
for (int u=1;u<=Dominos.n;u++)
for (int i=0;i<Dominos.group[u].size();i++)
{
int v=Dominos.group[u][i];
if (Dominos.sccno[u]!=Dominos.sccno[v]) indegree[Dominos.sccno[v]]++;
}
int ans=0;
for (int i=1;i<=Dominos.scc_cnt;i++)
if (indegree[i]==0) ans++;
printf("%d\n",ans);
}
return 0;
}

作者 chensunrise

时间: 2024-10-12 19:32:18

hust 1260 Dominos && hust 1516 Dominos的相关文章

[CSDN_Markdown]Markdown基本语法2

简介 前文 Markdown基本语法 中介绍了Markdown的基本语法,知道那些基本的语法,实际上已经可以写纯文本的博客了.对我们这群写代码的人或者将要写代码的人来说,貌似这些还不够,我们还希望能插入图片.代码.表格.超链接!此文分别介绍怎么在Markdown中用这些特性. 表格 如下表: 姓名 年龄 学历 张三 16 高中 李四 17 大学 王五 18 研究生 他的Markdown文本是: | 姓名 | 年龄 | 学历 | |:--- |:---:| ---:| | 张三 | 16 | 高中

Java File IO学习笔记

声明:以下转载自:Java中的File文件类详解 文件操作在Java的io操作中占有十分重要的地位,本文从以下几个方面来接受Java中对文件的操作. 1.Java中新建或者删除一个文件,文件夹以及createNewFile(),delete(),mkdir(),mkdirs()函数的使用. 2. 判断文件的函数:exists(),isFile(),isAbsolute(),isDirectory(),canRead(),canWrite(),isHidden()函数的使用. 3. 文件属性的函数

Hamcrest 总结

Junit JUnit框架用一组assert方法封装了一些常用的断言.这些assert方法可以帮我们简化单元测试的编写.这样的话,Junit就可以根据这些断言是否抛出 AssertionFailedError 错误来判断测试用例的执行结果. Hamcrest 使用过Junit 的应该有过体验:在实际开发中,一些基本的断言,如eqaul,null,true它们的可读性并不是很好.而且很多时候我们要比较对象.集合.Map等数据结构.这样我们要么进行大段的字段获取再断言.或者干脆自己编写表达式并断言其

hust 1511 Dominos 2

题目描述 Dominos are lots of fun. Children like to stand the tiles on their side in long lines. When one domino falls, it knocks down the next one, which knocks down the one after that, all the way down the line. However, sometimes a domino fails to knoc

HUST 1588 辗转数对

1588 - 辗转数对 时间限制:1秒 内存限制:128兆 155 次提交 27 次通过 题目描述 假设当前有一个数对(a, b),我们可以通过一步将这个数对变为一个新数对(a + b, b)或者是(a, a + b).初始的数对为(1, 1),你的任务是找到一个数字k,即通过最少的步数使得这个数对中至少一个数字等于n. 输入 输入包括多组数据,每组数据包括一行,每行有一个整数n. 输出 每组数据输出一行,每行一个整数n. 样例输入 5 3 样例输出 3 2 提示 第一个样例的方法是 (1,1)

HUST 1698 - 电影院 组合数学 + 分类思想

http://acm.hust.edu.cn/problem/show/1698 题目就是要把一个数n分成4段,其中中间两段一定要是奇数. 问有多少种情况. 分类, 奇数 + 奇数 + 奇数 + 奇数 奇数 + 奇数 + 奇数 + 偶数 偶数 + 奇数 + 奇数 + 奇数 偶数 + 奇数 + 奇数 + 偶数 然后奇数表达成 2 * a - 1这个样子,就能列出方程. 然后就是类似于解a1 + a2 + a3 + a4 = x的问题了. #include <cstdio> #include &l

HUST 1017 - Exact cover (Dancing Links 模板题)

1017 - Exact cover 时间限制:15秒 内存限制:128兆 自定评测 5584 次提交 2975 次通过 题目描述 There is an N*M matrix with only 0s and 1s, (1 <= N,M <= 1000). An exact cover is a selection of rows such that every column has a 1 in exactly one of the selected rows. Try to find o

勇士出征[HUST 1439]

勇士出征[HUST 1439] 时间1000ms,内存64MB 第十届"北大青鸟"杯浙江师范大学程序设计竞赛 这道题跟UVA-12100是一样的题目.我这里用的是STL的双端队列deque容器配合优先队列priority_queue,写起来会比较轻松:依次将输入压入队列,然后不断扫描队列,符合最大优先级的(优先队列的顶部元素)将其送出,而不再压入队尾.直到找到符合自己的标记的为止. 当然这道题也有用数组使用滚雪球的方式实现的,也就是开一个大的数组,每次将元素后挪时,直接将其放在数组末尾

UVALive 2659+HUST 1017+ZOJ 3209 (DLX

UVALive 2659 题目:16*16的数独.试了一发大白模板. /* * @author: Cwind */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include