题目是要给n个重量1到n的球编号,有一些约束条件:编号A的球重量要小于编号B的重量,最后就是要输出字典序最小的从1到n各个编号的球的重量。
正向拓扑排序,取最小编号给最小编号是不行的,不举出个例子真的很难理解= =比如这个数据:
1
4 2
4 1
3 2
正确答案是2 4 3 1,会得到的错误答案是4 2 1 3。
一开始我是用了贪心的做法,每次选未安排重量的最小的编号,安排给它尽量小的重量。某个编号能得到的最小的重量的计算是这样的:
- 计算出约束中重量要小于此编号的编号个数,记为k,这个可以先用Floyd预处理出任意两点间的连通性然后遍历一遍统计
- 因而这个编号能得到的最小重量就是第k个还没被用的重量
- 这时候还要回溯把所有约束中重量要小于到这个编号的编号给他们安排上k-1个重量
见代码:
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
bool map[][];
int n,m;
bool floyd(){
for(int k=; k<=n; ++k){
for(int i=; i<=n; ++i){
for(int j=; j<=n; ++j){
map[i][j]|=(map[i][k]&map[k][j]);
}
}
}
for(int i=; i<=n; ++i) if(map[i][i]) return ;
return ;
}
bool vis[];
int getk(int k){
for(int i=; i<=n; ++i){
if(!vis[i]) if(--k==) return i;
}
return ;
}
int d[];
void dfs(int u){
if(d[u]) return;
int cnt=;
for(int v=; v<=n; ++v){
if(map[v][u] && !d[v]) ++cnt;
}
d[u]=getk(cnt+);
vis[d[u]]=;
for(int v=; v<=n ;++v){
if(map[v][u]) dfs(v);
}
}
int main(){
int t,a,b;
scanf("%d",&t);
while(t--){
memset(d,,sizeof(d));
memset(map,,sizeof(map));
memset(vis,,sizeof(vis));
scanf("%d%d",&n,&m);
while(m--){
scanf("%d%d",&a,&b);
map[a][b]=;
}
if(!floyd()){
puts("-1");
continue;
}
for(int i=; i<=n; ++i){
dfs(i);
printf("%d ",d[i]);
}
putchar('\n');
}
return ;
}
事实上这题正解是反着进行拓扑排序,就是逆图中进行拓扑排序,取最大编号给最大重量。
正确性我是这么理解的:
当前安排的编号是x,有两个入度0的结点a和b,且a<b,按算法是给b球编号x。
反证法,假设给a球编号x能更优,那么
Case b: ...[ ]...[ ]...[x] [ ]... (weight[b]=x)
Case a: ...[y]...[x]...[ ] [ ]... (weight[a]=x)
在后面编号的安排中,就存在一个小于x的编号y被安排在了(Case a)中a的前面,且(Case b)不能做到字典序更小的。但这是不存在的,因为(Case b)马上就能把x-1这个编号安排在a位置,即weight[a]=x-1,这样(Case a)能做的(Case b)也能做了,且(Case b)编号还更小。
所以,选择b编号x比a编号x更优。
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define MAXN 222
#define MAXM 44444
struct Edge{
int u,v,next;
}edge[MAXM];
int NE,head[MAXN];
void addEdge(int u,int v){
edge[NE].u=u; edge[NE].v=v; edge[NE].next=head[u];
head[u]=NE++;
}
int deg[MAXN],size[MAXN];
bool toposort(int n){
priority_queue<int> que;
for(int i=; i<=n; ++i){
if(deg[i]==) que.push(i);
}
for(int k=n; k>=; --k){
if(que.empty()) return ;
int u=que.top(); que.pop();
size[u]=k;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(--deg[v]==) que.push(v);
}
}
return ;
}
int main(){
int t,n,m,a,b;
scanf("%d",&t);
while(t--){
NE=;
memset(head,-,sizeof(head));
memset(deg,,sizeof(deg));
scanf("%d%d",&n,&m);
while(m--){
scanf("%d%d",&a,&b);
addEdge(b,a);
++deg[a];
}
if(toposort(n)){
for(int i=; i<=n; ++i) printf("%d ",size[i]);
putchar('\n');
}else puts("-1");
}
return ;
}
POJ3687 Labeling Balls(拓扑排序\贪心+Floyd)的更多相关文章
-
POJ3687.Labeling Balls 拓扑排序
Labeling Balls Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13201 Accepted: 3811 Descr ...
-
PKU 3687 Labeling Balls(拓扑排序)
题目大意:原题链接 给出N个未编号的质量各不相同的球,以及它们质量轻重的大小关系,给它们从1-N贴标签编号,无重复.问是否存在可行的编号方法,不存在输出-1, 如果存在则输出唯一一种方案,此方案是使得 ...
-
[ACM] POJ 3687 Labeling Balls (拓扑排序,反向生成端)
Labeling Balls Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10161 Accepted: 2810 D ...
-
[poj3687]Labeling Balls_拓扑排序
Labeling Balls poj-3687 题目大意:给出一些球之间的大小关系,求在满足这样的关系下,编号小的尽量比编号大的球的方案. 注释:1<=N(球的个数)<=200,1< ...
-
poj 3687 Labeling Balls(拓扑排序)
题目:http://poj.org/problem?id=3687题意:n个重量为1~n的球,给定一些编号间的重量比较关系,现在给每个球编号,在符合条件的前提下使得编号小的球重量小.(先保证1号球最轻 ...
-
Java实现Labeling Balls(拓扑排序的应用)
1 问题描述 给出一些球,从1N编号,他们的重量都不相同,也用1N标记加以区分(这里真心恶毒啊,估计很多WA都是因为这里),然后给出一些约束条件,< a , b >要求编号为 a 的球必须 ...
-
POJ3687——Labeling Balls(反向建图+拓扑排序)
Labeling Balls DescriptionWindy has N balls of distinct weights from 1 unit to N units. Now he tries ...
-
BZOJ_4010_[HNOI2015]菜肴制作_拓扑排序+贪心
BZOJ_4010_[HNOI2015]菜肴制作_拓扑排序+贪心 Description 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜 ...
-
POJ3687拓扑排序+贪心
题意: 给你n个求,他们的重量是1-n(并不是说1号求的重量是1...),然后给你m组关系a,b,表示a的重量小于b的重量,然后让你输出满足要求的前提下每个球的重量,要求字典序最小. 思路 ...
随机推荐
-
分布式架构高可用架构篇_07_MySQL主从复制的配置(CentOS-6.7+MySQL-5.6)
参考: 龙果学院http://www.roncoo.com/share.html?hamc=hLPG8QsaaWVOl2Z76wpJHp3JBbZZF%2Bywm5vEfPp9LbLkAjAnB%2B ...
-
Mysql 自定义随机字符串
前几天在开发一个系统,需要用到随机字符串,但是mysql的库函数有没有直接提供,就简单的利用现有的函数东拼西凑出随机字符串来.下面简单的说下实现当时. 1.简单粗暴. select ..., subs ...
-
关于NotePad++ v1.0的编译和源码分析
最近想读读开源项目,windows下的.文本编辑器是一个很好的选择,因为里面的很多技术,算法(字符串搜索,匹配等)都是被程序员实现过千万遍了,代码里面有很多精髓可以让我们这些菜鸟学学. 首先:下载源码 ...
-
HDU 4664 Triangulation【博弈论】
一个平面上有n个点(一个凸多边形的顶点),每次可以连接一个平面上的两个点(不能和已经连接的边相交),如果平面上已经出现了一个三角形,则不能在这个平面上继续连接边了. 现在总共有N个平面,每个平面上都有 ...
-
linux上静态库链接的有关问题
求大神,linux下静态库链接的问题有两个文件和一个库,a.c, b.c,libh.a,其中b.c里面会有调用libh.a的函数func1,现在将a.c, b.c,libh.a编译链接生成可执行文件, ...
-
1. Ansible 简介
目录 1. Ansible 是什么? 2. Ansible 特性 3. 控制主机需求 4. 被管理节点需求 1. Ansible 是什么? Ansible 是一个配置管理系统(configuratio ...
-
LODOP打印控件如何提示用户升级下载安装新版本
Lodop.C-Lodop在不断完善功能和更新中,新版本修复了很多问题,以及增加很多有利的功能,网站如何更新版本,提示用户下载新版本呢?更新版本很简单,只需要三步:1.替换提示安装部分的自己放置的路径 ...
-
语法对照表ES5VSES6
模块 导入 在ES5里面,如果使用CommonJS的标准,引入包一般是使用require来的 //ES5 js var React = require("react") var { ...
-
If TransactionScope will close database connections
问 Do TransactionScope work with closed database connections? using (var transaction = new Transactio ...
-
QT学习2
一.常用控件与常用的功能函数. QDialog.QMainWindow.QPushButton.QLabel.QLineEdit 构造函数指定父容器.setText,getText,size,res ...