Air Raid

Language:Default
Air Raid
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 9547 Accepted: 5696

Description

Consider a town where all the streets are one-way and each street leads from one intersection to another. It is also known that starting from an intersection and walking through town's streets you can never reach the same intersection i.e. the town's streets form no cycles.



With these assumptions your task is to write a program that finds the minimum number of paratroopers that can descend on the town and visit all the intersections of this town in such a way that more than one paratrooper visits no intersection. Each paratrooper lands at an intersection and can visit other intersections following the town streets. There are no restrictions about the starting intersection for each paratrooper.

Input

Your program should read sets of data. The first line of the input file contains the number of the data sets. Each data set specifies the structure of a town and has the format:



no_of_intersections

no_of_streets

S1 E1

S2 E2

......

Sno_of_streets Eno_of_streets



The first line of each data set contains a positive integer no_of_intersections (greater than 0 and less or equal to 120), which is the number of intersections in the town. The second line contains a positive integer no_of_streets, which is the number of streets in the town. The next no_of_streets lines, one for each street in the town, are randomly ordered and represent the town's streets. The line corresponding to street k (k <= no_of_streets) consists of two positive integers, separated by one blank: Sk (1 <= Sk <= no_of_intersections) - the number of the intersection that is the start of the street, and Ek (1 <= Ek <= no_of_intersections) - the number of the intersection that is the end of the street. Intersections are represented by integers from 1 to no_of_intersections.



There are no blank lines between consecutive sets of data. Input data are correct.

Output

The result of the program is on standard output. For each input data set the program prints on a single line, starting from the beginning of the line, one integer: the minimum number of paratroopers required to visit all the intersections in the town.

Sample Input

2
4
3
3 4
1 3
2 3
3
3
1 3
1 2
2 3

Sample Output

2
1

Source

有n个点和m条有向边,现在要在点上放一些伞兵,然后伞兵沿着图走,直到不能走为止

每条边只能是一个伞兵走过,问最少放多少个伞兵

题解

这就是最小路径点覆盖模板题。

拆点成出入点,连边,答案为n-最大匹配。

#include<iostream>
#include<bitset>
#include<cstring>
#include<vector>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
using namespace std; co int N=301;
int n,m,f[N];
vector<int> e[N];
bitset<N> v;
bool dfs(int x){
for(unsigned i=0;i<e[x].size();++i){
int y=e[x][i];
if(v[y]) continue;
v[y]=1;
if(!f[y]||dfs(f[y])){
f[y]=x;
return 1;
}
}
return 0;
}
void Air_Raid(){
read(n),read(m);
for(int i=1;i<=n;++i) e[i].clear();
for(int x,y;m--;){
read(x),read(y);
e[x].push_back(y);
}
memset(f,0,sizeof f);
int ans=0;
for(int i=1;i<=n;++i){
v<<=n;
ans+=dfs(i);
}
printf("%d\n",n-ans);
}
int main(){
for(int t=read<int>();t--;) Air_Raid();
return 0;
}

6902 Vani和Cl2捉迷藏 0x60「图论」例题

描述

Vani和cl2在一片树林里捉迷藏。这片树林里有N座房子,M条有向道路,组成了一张有向无环图。N≤200,M≤30000。

树林里的树非常茂密,足以遮挡视线,但是沿着道路望去,却是视野开阔。如果从房子A沿着路走下去能够到达B,那么在A和B里的人是能够相互望见的。

现在cl2要在这N座房子里选择K座作为藏身点,同时Vani也专挑cl2作为藏身点的房子进去寻找,为了避免被Vani看见,cl2要求这K个藏身点的任意两个之间都没有路径相连。

为了让Vani更难找到自己,cl2想知道最多能选出多少个藏身点。

输入格式

输入数据的第一行是两个整数N和M。接下来M行,每行两个整数 x,y,表示一条从 x 到 y 的有向道路。

输出格式

输出一个整数K,表示最多能选取的藏身点个数。

在第二行输出 K 个空格分开的整数,表示选择的藏身点编号。如果有多个方案,输出任意一个即可。编号的输出顺序任意。

样例输入

7 5
1 2
3 2
2 4
4 5
4 6

样例输出

3
1 3 7

数据范围与约定

  • 对于20% 的数据,N≤10,M<=20。

    对于60% 的数据, N≤100,M<=1000。

    对于100% 的数据,N≤200,M<=30000,1<=x,y<=N。

本题校验器(SPJ)

01 #include <iostream>
02 #include <cstdio>
03 #include <cstring>
04 #include <algorithm>
05 #include <vector>
06 using namespace std;
07 //一些定义
08 const int ACCEPT = 0;
09 const int WRONG_ANSWER = 1;
10 //fstd 标准输出 fout 选手输出 fin 标准输入
11 FILE *fstd,*fout,*fin;
12 int n, m, ans, val;
13 bool v[210], f[210];
14 vector<int> ver[210];
15  
16 bool dfs(int x) {
17     f[x] = 1;
18     if (v[x]) return true;
19     for (int i = 0; i < ver[x].size(); i++) {
20         int y = ver[x][i];
21         if (f[y]) continue;
22         if (dfs(y)) return true;
23     }
24     return false;
25 }
26  
27 //执行比较操作。
28 bool DoCompare(){
29     fscanf(fin, "%d%d", &n, &m);
30     for (int i = 1; i <= m; i++) {
31         int x, y;
32         fscanf(fin, "%d%d", &x, &y);
33         ver[x].push_back(y);
34     }
35     fscanf(fstd, "%d", &ans);
36     fscanf(fout, "%d", &val);
37     // 答案不对
38     if (val != ans) return false;
39     for (int i = 1; i <= ans; i++) {
40         int x; fscanf(fout, "%d", &x);
41         // 输出的藏身点不合法或有重复
42         if (x < 1 || x > n || v[x]) return false;
43         v[x] = 1;
44     }
45     for (int i = 1; i <= n; i++) {
46         if (!v[i]) continue;
47         memset(f, 0, sizeof(f));
48         v[i] = 0;
49         // 能看到别的点
50         if (dfs(i)) return false;
51         v[i] = 1;
52     }
53     return true;
54 }
55  
56 int main(int argc, char* argv[])
57 {
58     if(argc!=4){
59         printf("参数不足 %d",argc);
60         return -1;
61     }
62  
63     //打开文件
64     if(NULL==(fstd=fopen(argv[1],"r"))){
65         return -1;
66     }
67     if(NULL==(fout=fopen(argv[2],"r"))){
68         return -1;
69     }
70     if(NULL==(fin=fopen(argv[3],"r"))){
71         return -1;
72     }
73  
74     if(DoCompare()){
75         return ACCEPT;
76     }else{
77         return WRONG_ANSWER;
78     }
79 }
        </article>

题解

藏身点个数等于最小路径可重复点覆盖包含的路径条数。只需传递闭包,拆点跑二分图最大匹配,用点数减去它就行了。

证明见《进阶》,是一个利用了反证法的构造。

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll; co int N=201;
bool cl[N][N];
int match[N],n,m;
bool vis[N],succ[N];
int hide[N]; bool dfs(int x){
for(int i=1;i<=n;++i)
if(cl[x][i]&&!vis[i]){
vis[i]=1;
if(!match[i]||dfs(match[i])){
match[i]=x;
return 1;
}
}
return 0;
}
int main(){
read(n),read(m);
while(m--) cl[read<int>()][read<int>()]=1;
for(int i=1;i<=n;++i) cl[i][i]=1;
for(int k=1;k<=n;++k)
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
cl[i][j]|=cl[i][k]&cl[k][j];
for(int i=1;i<=n;++i) cl[i][i]=0;
// Maximum Matching on Split Bipartite Graph
int ans=n;
for(int i=1;i<=n;++i){
memset(vis,0,sizeof vis);
ans-=dfs(i);
}
printf("%d\n",ans);
for(int i=1;i<=n;++i) succ[match[i]]=1;
for(int i=1,k=0;i<=n;++i)
if(!succ[i]) hide[++k]=i;
memset(vis,0,sizeof vis);
for(bool modify=1;modify;){
modify=0;
for(int i=1;i<=ans;++i)
for(int j=1;j<=n;++j)
if(cl[hide[i]][j]) vis[j]=1;
for(int i=1;i<=ans;++i)
if(vis[hide[i]]){
modify=1;
while(vis[hide[i]]) hide[i]=match[hide[i]];
}
}
for(int i=1;i<=ans;++i) printf("%d ",hide[i]);
return 0;
}

POJ1422 Air Raid 和 CH6902 Vani和Cl2捉迷藏的更多相关文章

  1. POJ1422 Air Raid 【DAG最小路径覆盖】

    Air Raid Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6763   Accepted: 4034 Descript ...

  2. 【JZOJ3423】Vani和Cl2捉迷藏&【BZOJ1143】祭祀river

    description vani和cl2在一片树林里捉迷藏-- 这片树林里有N座房子,M条有向道路,组成了一张有向无环图. 树林里的树非常茂密,足以遮挡视线,但是沿着道路望去,却是视野开阔.如果从房子 ...

  3. POJ1422 Air Raid

    Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 8006   Accepted: 4803 Description Consi ...

  4. 「Poetize5」Vani和Cl2捉迷藏

    描述 Description 这片树林里有N座房子,M条有向道路,组成了一张有向无环图.树林里的树非常茂密,足以遮挡视线,但是沿着道路望去,却是视野开阔.如果从房子A沿着路走下去能够到达B,那么在A和 ...

  5. [tyvj1957 Poetize5] Vani和Cl2捉迷藏 (最小路径可重点覆盖+二分图最大匹配)

    传送门 Description 这片树林里有N座房子,M条有向道路,组成了一张有向无环图. 树林里的树非常茂密,足以遮挡视线,但是沿着道路望去,却是视野开阔.如果从房子A沿着路走下去能够到达B,那么在 ...

  6. codevs 2494 Vani和Cl2捉迷藏

    /* 一开始大意了 以为和bzoj上的祭祀是一样的(毕竟样例都一样) 这里不知相邻的点可以相互到达 间接相连的也可以到达 所以floyed先建立一下关系 再跑最大独立集 下面贴一下95 和 100的代 ...

  7. CODE[VS]2494 Vani和Cl2捉迷藏

    原题链接 这里有一个结论:最多能选取的藏身点个数等于最小路径可重复点覆盖的路径总数. 所以我们可以先传递闭包,然后求最小路径点覆盖即可. #include<cstdio> #include ...

  8. joyoi1957 「Poetize5」Vani和Cl2捉迷藏

    最小路径可重点覆盖.先传递闭包,然后拆点,\(n-\)最大匹配,看算法竞赛进阶指南. #include <iostream> #include <cstring> #inclu ...

  9. Air Raid[HDU1151]

    Air RaidTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

随机推荐

  1. 如何更好的利用Node.js的性能极限

    通过使用非阻塞.事件驱动的I/O操作,Node.js为构建和运行大规模网络应用及服务提供了很好的平台,也受到了广泛的欢迎.其主要特性表现为能够处理庞大的并且高吞吐量的并发连接,从而构建高性能.高扩展性 ...

  2. mysql慢查询日志分析工具(python写的)

    D:\NormalSoftware>python mysql_filter_slow_log.py ./mysql1-slow.log --no-duplicates --sort-avg-qu ...

  3. Unity3d监听手机暂停与退出事件

    做移动互联网类型的开放,很多情况得考虑移动设备的暂停与退出时,做某些数据操作或UI. 1,退出事件,Unity3d,InPut就包含了: Input.GetKey(KeyCode.Escape) .  ...

  4. 20179209《Linux内核原理与分析》第十一周作业

    Nmap配合Metasploit进行端口扫描 1.Nmap扫描器基本使用 1.1简介 Nmap(Network Mapper)最早是Linux下的网络扫描嗅探器.其基本功能有三个: 探测一组主机是否在 ...

  5. 【网络与系统安全】20179209 wireshark和nmap实验

    TCP三次握手包 在进行实验前,先梳理一遍TCP三次握手的过程,这个图是我本科学网络时画过不少于十遍的图,我觉得非常有纪念意义. 稍作解释,第一次握手,客户端发起请求连接,发送一个标志位为SYN的ip ...

  6. lua面向对象封装

    lua面向对象的一个封装,直接贴代码 --swfclass = {};local cs = {};function _class( child, base, ... )--    _.s( child ...

  7. CMDB的四种模式

    为什么要有CMDB? CMDB --Configuration Management Database 配置管理数据库. 1.为了实现资产的自动采集,资产的自动更新, 为了搭建公司自动化平台的基础则需 ...

  8. 短时程突触可塑性(short-term synaptic plasticity)

    介绍 神经元的突触可塑性一般被认为是大脑学习与记忆的分子生物学机制,它是指突触传递效率增强或减弱的变化现象.若这种变化只持续数十毫秒到几分,便称之为短时程突触可塑性,其中效率增强与减弱分别叫做短时程增 ...

  9. JavaScript螺旋矩阵

    螺旋矩阵                                                           螺旋矩阵指一个呈螺旋状的矩阵,其数字由第一行开始到右边不断变大,向下变大, ...

  10. 【HTTP】HTPP学习笔记

    1.了解web及网络基础 HTTP的诞生 TCP/IP协议族 应用层 FTP文件传输协议 HTTP超文本传输协议 DNS域名系统:IP地址<--->域名 传输层 TCP传输控制协议 三次握 ...