题目是要给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)的更多相关文章

  1. POJ3687.Labeling Balls 拓扑排序

    Labeling Balls Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13201 Accepted: 3811 Descr ...

  2. PKU 3687 Labeling Balls(拓扑排序)

    题目大意:原题链接 给出N个未编号的质量各不相同的球,以及它们质量轻重的大小关系,给它们从1-N贴标签编号,无重复.问是否存在可行的编号方法,不存在输出-1, 如果存在则输出唯一一种方案,此方案是使得 ...

  3. [ACM] POJ 3687 Labeling Balls (拓扑排序,反向生成端)

    Labeling Balls Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10161   Accepted: 2810 D ...

  4. [poj3687]Labeling Balls_拓扑排序

    Labeling Balls poj-3687 题目大意:给出一些球之间的大小关系,求在满足这样的关系下,编号小的尽量比编号大的球的方案. 注释:1<=N(球的个数)<=200,1< ...

  5. poj 3687 Labeling Balls(拓扑排序)

    题目:http://poj.org/problem?id=3687题意:n个重量为1~n的球,给定一些编号间的重量比较关系,现在给每个球编号,在符合条件的前提下使得编号小的球重量小.(先保证1号球最轻 ...

  6. Java实现Labeling Balls(拓扑排序的应用)

    1 问题描述 给出一些球,从1N编号,他们的重量都不相同,也用1N标记加以区分(这里真心恶毒啊,估计很多WA都是因为这里),然后给出一些约束条件,< a , b >要求编号为 a 的球必须 ...

  7. POJ3687——Labeling Balls(反向建图+拓扑排序)

    Labeling Balls DescriptionWindy has N balls of distinct weights from 1 unit to N units. Now he tries ...

  8. BZOJ_4010_[HNOI2015]菜肴制作_拓扑排序+贪心

    BZOJ_4010_[HNOI2015]菜肴制作_拓扑排序+贪心 Description 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜 ...

  9. POJ3687拓扑排序+贪心

    题意:       给你n个求,他们的重量是1-n(并不是说1号求的重量是1...),然后给你m组关系a,b,表示a的重量小于b的重量,然后让你输出满足要求的前提下每个球的重量,要求字典序最小. 思路 ...

随机推荐

  1. CSS简写指南

    高效的css写法中的一条就是使用简写.通过简写可以让你的CSS文件更小,更易读.而了解CSS属性简写也是前端开发工程师的基本功之一.今天我们系统地总结一下CSS属性的缩写. 色彩缩写 色彩的缩写最简单 ...

  2. session 实现登录功能注意事项

    php5之后废除了session_unregister()函数,可以用 session_destory().其他的也都没有啥了,还有就是输出嵌入的PHP代码用=代码见我的git:https://git ...

  3. 计蒜客 X的平方根

    X的平方根 设计函数int sqrt(int x),计算x的平方根. 格式: 输入一个数x,输出它的平方根.直到碰到结束符号为止. 千万注意:是int类型哦- 输入可以如下操作: while(cin& ...

  4. MySQL sql语句总结

    1.说明:创建数据库CREATE DATABASE database-name2.说明:删除数据库drop database dbname3.说明:备份sql server--- 创建 备份数据的 d ...

  5. delphi 枚举类型

    枚举类型定义了一系列有序值的集合.枚举变量就是从这个既定的集合中取某个值.集合中的有序值可以称为元素,元素一般从0开始索引(也就是元素的顺序号). 定义一个枚举类型,采用以下的格式: type typ ...

  6. zookeeper 配置详解

    http://blog.csdn.net/shenlan211314/article/details/6185176  因博主原创,所以不能转载 下面是更为详细的配置说明: 前面两篇文章介绍了Zook ...

  7. linux rsync +inotify 实现 实时同步

    前言:     rsync可以实现触发式的文件同步,但是通过crontab守护进程方式进行触发,同步的数据和实际数据会有差异,而inotify可以监控文件系统的各种变化,当文件有任何变动时,就触发rs ...

  8. HDOJ 1301

    9852303 2013-12-18 11:47:01 Accepted 1301 0MS 264K 1117 B C++ 泽泽 Jungle Roads Time Limit: 2000/1000 ...

  9. Javascript样例之文档章节滚动全版(DOM)

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABBMAAAC5CAIAAAD1bOCRAAAMEUlEQVR4nO3d4XEbyREGUGRCZQDGcG

  10. Django authentication 使用方法

    转自 : https://docs.djangoproject.com/en/1.8/topics/auth/customizing/