POJ3687 Labeling Balls(拓扑排序\贪心+Floyd)
题目是要给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的重量,然后让你输出满足要求的前提下每个球的重量,要求字典序最小. 思路 ...
随机推荐
- 黑色30s高并发IIS设置
在这篇博文中,我们抛开对阿里云的怀疑,完全从ASP.NET的角度进行分析,看能不能找到针对问题现象的更合理的解释. “黑色30秒”问题现象的主要特征是:排队的请求(Requests Queued)突增 ...
- HDU 4915 Parenthese sequence
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4915 解题报告:从前往后遍历一次,每次判断')'的数目是不是满足 n < (i +1)/ 2,从 ...
- Unity3D研究院之动态修改烘培贴图的大小&脚本烘培场景
Unity默认烘培场景以后每张烘培贴图的大小是1024.但是有可能你的场景比较简单,用1024会比较浪费.如下图所示,这是我的一个场景的烘培贴图,右上角一大部分完全是没有用到,但是它却占着空间. 有 ...
- iOS高级必备
1.你使用过Objective-C的运行时编程(Runtime Programming)么?如果使用过,你用它做了什么?你还能记得你所使用的相关的头文件或者某些方法的名称吗? Objecitve-C的 ...
- 代码风格与树形DP
Streaming很惨,不过因为比赛之间没有提交过就没掉(或掉了)rating.第二题是一个树形DP,但是我都在想第一题了,简直作死. 看着神犇的代码我也是醉了...各种宏,真是好好写会死系列. 看到 ...
- Java常用排序算法+程序员必须掌握的8大排序算法
概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. 当n较大, ...
- 【转】mysql忘记root密码的解决方法
本文收集于本人的笔记本,由于找不到原文出处.在此省略,如哪位知道可以联系我加上. 方法一:在windows下:1.打开命令行(DOS)窗口,停止mysql服务: net stop mysql 2.在D ...
- codeforces A. New Year Candles 解题报告
题目链接:http://codeforces.com/problemset/problem/379/A 题目意思:给定a支蜡烛(每支蜡烛可以燃烧1小时),可以在燃尽的a支蜡烛中看能组成多少组b支蜡烛, ...
- css样式自适应,支持数字
td加上style="word-break: break-all;word-wrap: break-word;"样式即可
- 分页管理的AJAX实现
bookMgr.jsp <%-- Document : bookMgr.jsp Created on : 2016-11-7, 9:48:21 Author : guanghe --%> ...