poj 3275 "Ranking the Cows"(DFS or Floyd+bitset<>)
题意:
农场主 FJ 有 n 头奶牛,现在给你 m 对关系(x,y)表示奶牛x的产奶速率高于奶牛y;
FJ 想按照奶牛的产奶速率由高到低排列这些奶牛,但是这 m 对关系可能不能精确确定这 n 头奶牛的关系;
问最少需要额外增加多少对关系使得可以确定这 n 头奶牛的顺序;
题解:
之所以做这道题,是因为在补CF的题时用到了bitset<>;
搜这个容器的用法是看到了一篇标题为POJ-3275:奶牛排序Ranking the Cows(Floyd、bitset)的文章;
正好拿着道题练练bitset<>;
但是一做,发现,这道题和省赛的L题好像啊,做法完全相同,只是在输出结果上处理了一下;
下午在补一下如何用bitset<>做这道题,先贴上DFS暴力AC代码;
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=1e3+; int n,m;
int num;
int head[maxn];
struct Edge
{
int to;
int next;
}G[maxn**];
void addEdge(int u,int v)
{
G[num]={v,head[u]};
head[u]=num++;
}
bool vis[maxn]; int DFS(int u)
{
int ans=;
vis[u]=true;
for(int i=head[u];~i;i=G[i].next)
{
int v=G[i].to;
if(vis[v] || (i&))
continue;
ans += DFS(v);
}
return ans;
}
int RDFS(int u)
{
int ans=;
vis[u]=true;
for(int i=head[u];~i;i=G[i].next)
{
int v=G[i].to;
if(vis[v] || !(i&))
continue;
ans += RDFS(v);
}
return ans;
}
int Solve()
{
int ans=;
for(int i=;i <= n;++i)
{
mem(vis,false);
int t1=DFS(i);
mem(vis,false);
int t2=RDFS(i);
///第i头奶牛可以确定的奶牛个数为t1+t2-1
ans += n-(t1+t2-);
}
return ans>>;
}
void Init()
{
num=;
mem(head,-);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
Init();
for(int i=;i <= m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
addEdge(u,v);
addEdge(v,u);
}
printf("%d\n",Solve());
}
return ;
}
思路2:(来自上述链接文章)
确定这 n 头奶牛的顺序需要 n*(n-1)/2 对关系;
(X,Y)代表 rankX > rankY
已知关系 (X,Y),(Y,Z),那么,根据传递性可得隐藏关系(X,Z);
如何根据给出的m条关系找到所有的隐藏关系呢?
Floyd传递闭包;
AC代码1:
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=1e3+; int n,m;
bool e[maxn][maxn];
vector<int >in[maxn],out[maxn];
///in[u]:指向u的节点,out[u]:u指出去的节点 int Solve()
{
int ans=;
for(int k=;k <= n;++k)
{
for(int i=;i < in[k].size();++i)
{
for(int j=;j < out[k].size();++j)
{
int u=in[k][i];
int v=out[k][j];
if(!e[u][v])///隐藏关系u->v
{
e[u][v]=true;
out[u].push_back(v);
in[v].push_back(u);
ans++;
}
}
}
}
///m:已知关系对
///ans:隐藏关系对
return n*(n-)/-m-ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i <= m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
in[v].push_back(u);
out[u].push_back(v);
e[u][v]=true;
}
printf("%d\n",Solve()); return ;
}
另一种写法就是用到了bitset<>容器;
bitset<>_bit[];
对于输入的关系<u,v>;
_bit[u].set(v);//将第v为置位1,表示有一条u->v的边
如何找到所有的隐藏关系呢?
for(int i=;i <= n;++i)
for(int j=;j <= n;++j)
if(_bit[j][i])
_bit[j] |= _bit[i];///让j节点指向i节点所有指出去的边
晚上一直困惑,为什么将if()及其之后的语句改为
if(_bit[i][j])
_bit[i] |= _bit[j];
就wa了,找了许久,终于找到了;
对于如下关系:
(①,③) , (③,②) , (②,④)
(①->③->②->④)
当 i = 1 时,如果按照更改后的写法,①只会更新出<①,②>而不会更新出关系<①,④>(纸上画一下就出来了);
所以说,要更新内层循环的节点,这样更新的彻底;
AC代码2:
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<bitset>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=1e3+; int n,m;
bitset<maxn>_bit[maxn]; int Solve()
{
for(int i=;i <= n;++i)
for(int j=;j <= n;++j)
if(_bit[j][i])
_bit[j] |= _bit[i];///让j节点指向i节点所有指出去的边 int ans=;
for(int i=;i <= n;++i)
ans += _bit[i].count(); ///ans:m对已有关系对+隐藏关系对
return n*(n-)/-ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i <= m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
_bit[u].set(v);
}
printf("%d\n",Solve()); return ;
}
poj 3275 "Ranking the Cows"(DFS or Floyd+bitset<>)的更多相关文章
- POJ 3275 Ranking the Cows(传递闭包)【bitset优化Floyd】+【领接表优化Floyd】
<题目链接> 题目大意:FJ想按照奶牛产奶的能力给她们排序.现在已知有N头奶牛$(1 ≤ N ≤ 1,000)$.FJ通过比较,已经知道了M$1 ≤ M ≤ 10,000$对相对关系.每一 ...
- POJ 3275 Ranking the cows ( Floyd求解传递闭包 && Bitset优化 )
题意 : 给出 N 头牛,以及 M 个某些牛之间的大小关系,问你最少还要确定多少对牛的关系才能将所有的牛按照一定顺序排序起来 分析 : 这些给出的关系想一下就知道是满足传递性的 例如 A > B ...
- POJ 3187 Backward Digit Sums (dfs,杨辉三角形性质)
FJ and his cows enjoy playing a mental game. They write down the numbers from 1 to N (1 <= N < ...
- POJ 3621:Sightseeing Cows(最优比率环)
http://poj.org/problem?id=3621 题意:有n个点m条有向边,每个点有一个点权val[i],边有边权w(i, j).找一个环使得Σ(val) / Σ(w)最大,并输出. 思路 ...
- POJ 1330 Nearest Common Ancestors (dfs+ST在线算法)
详细讲解见:https://blog.csdn.net/liangzhaoyang1/article/details/52549822 zz:https://www.cnblogs.com/kuang ...
- POJ 1470 Closest Common Ancestors(最近公共祖先 LCA)
POJ 1470 Closest Common Ancestors(最近公共祖先 LCA) Description Write a program that takes as input a root ...
- POJ 1236 Network of Schools(强连通 Tarjan+缩点)
POJ 1236 Network of Schools(强连通 Tarjan+缩点) ACM 题目地址:POJ 1236 题意: 给定一张有向图,问最少选择几个点能遍历全图,以及最少加入�几条边使得 ...
- POJ 3436 ACM Computer Factory (网络流,最大流)
POJ 3436 ACM Computer Factory (网络流,最大流) Description As you know, all the computers used for ACM cont ...
- 【POJ 2750】 Potted Flower(线段树套dp)
[POJ 2750] Potted Flower(线段树套dp) Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4566 ...
随机推荐
- QLabel添加Click信号
使用自定义label来实现此功能 其他控件可参照此例. #include "customerqlabel.h" CustomerQlabel::CustomerQlabel(QWi ...
- Permutations II 去掉重复的全排列
Given a collection of numbers that might contain duplicates, return all possible unique permutations ...
- 【JZOJ3885】【长郡NOIP2014模拟10.22】搞笑的代码
ok 在OI界存在着一位传奇选手--QQ,他总是以风格迥异的搞笑代码受世人围观 某次某道题目的输入是一个排列,他使用了以下伪代码来生成数据 while 序列长度<n do { 随机生成一个整数属 ...
- docker入门 基础命令 docker安装
docker入门 在学一门新知识的时候,超哥喜欢提问,why?what?how? wiki资料 什么是docker Docker 最初是 dotCloud 公司创始人 Solomon Hykes ...
- JS对HTML实体字符转义和反转义
一.名词解释 HTML实体字符: 由于在HTML中有些符号是预留的,比如在html中不能直接使用尖括号(‘<’或‘>’),会被误认为标签符号.所以需要通过HTML实体字符去进行替换: HT ...
- django其他
聚合查询 聚合函数必须在分组之后使用 没有分组默认整体为一组 聚合函数 Max, Min, Sum, Avg, Count 从django.db.models 导入方法,然后使用关键字aggregat ...
- BKDRHash算法的初步了解
字符串hash最高效的算法, 搜了一下, 原理是: 字符串的字符集只有128个字符,所以把一个字符串当成128或更高进制的数字来看,当然是唯一的 这里unsigned不需要考虑溢出的问题, 不过 ...
- Java排序需掌握算法 详解
package com.sxt.review; /*内部排序:(在内存) * 插入排序-->希尔排序 * 冒泡排序-->快速排序 * 选择排序-->堆排序 * 归并排序 * 基数排序 ...
- Effective C++: 01让自己习惯C++
01:视C++为一个语言联邦 1:今天的C++已经是个多重范型编程语言(multiparadigm programming language),一个同时支持过程形式(procedural).面向对象形 ...
- Python中基于socketserver实现并发的socket
1.基于TCP协议: 服务端: import socketserver class MyHandler(socketserver.BaseRequestHandler): def handle(sel ...