贴标签
2016-08-24 09:20
225 查看
罗老师正在给一堆球贴标签,总共有N个球,要给他们贴1-N的编号,不能重复。
罗老师首先将这N个球排成一排,排好后,突然想给自己找点麻烦(无聊),就想出了M条限制条件,每个条件是:
A B
表示第A个球的编号要小于第B个球的编号。
当然,限制条件会造成有时答案有很多种,那么罗老师希望贴好标签后的球字典序最小;也有可能答案不存在,那么就输出-1。
输入
首先输入T,表示有T组测试数据
然后每组测试数据首先输入N, M
接下来M行每行输入A B,表示第A个球编号要小于第B个球
输出
如果答案存在,输出最小字典序(数字字典序,也就是优先小数字在前,比如 22 在 111前)不存在就输出”-1”
样例输入
5
4 0
4 1
1 1
4 2
1 2
2 1
4 1
2 1
4 1
3 2
样例输出
1 2 3 4
-1
-1
2 1 3 4
1 3 2 4
提示
【数据规模和约定】
1<=N<=200 0<=M<=40000 可能有重边
题意:n个重量为1−n的球,给定一些编号间的重量比较关系,现在给每个球编号,在符合条件的前提下使得编号小的球重量小。(先保证1号球最轻,其次2号……)
分析:拓扑排序,注意根据题的要求,要先保证1号球最轻,如果我们由轻的向重的连边,然后我们依次有小到大每次把重量分给一个入度为0的点,那么在拓扑时我们面对多个入度为0的点,我们不知道该把最轻的分给谁才能以最快的速度找到1号(使1号入度为0),并把当前最轻的分给1号。所以我们要由重的向轻的连边,然后从大到小每次把一个重量分给一个入度为0的点。这样我们就不用急于探求最小号。我们只需要一直给最大号附最大值,尽量不给小号赋值,这样自然而然就会把轻的重量留给小号。
注意重边。
罗老师首先将这N个球排成一排,排好后,突然想给自己找点麻烦(无聊),就想出了M条限制条件,每个条件是:
A B
表示第A个球的编号要小于第B个球的编号。
当然,限制条件会造成有时答案有很多种,那么罗老师希望贴好标签后的球字典序最小;也有可能答案不存在,那么就输出-1。
输入
首先输入T,表示有T组测试数据
然后每组测试数据首先输入N, M
接下来M行每行输入A B,表示第A个球编号要小于第B个球
输出
如果答案存在,输出最小字典序(数字字典序,也就是优先小数字在前,比如 22 在 111前)不存在就输出”-1”
样例输入
5
4 0
4 1
1 1
4 2
1 2
2 1
4 1
2 1
4 1
3 2
样例输出
1 2 3 4
-1
-1
2 1 3 4
1 3 2 4
提示
【数据规模和约定】
1<=N<=200 0<=M<=40000 可能有重边
题意:n个重量为1−n的球,给定一些编号间的重量比较关系,现在给每个球编号,在符合条件的前提下使得编号小的球重量小。(先保证1号球最轻,其次2号……)
分析:拓扑排序,注意根据题的要求,要先保证1号球最轻,如果我们由轻的向重的连边,然后我们依次有小到大每次把重量分给一个入度为0的点,那么在拓扑时我们面对多个入度为0的点,我们不知道该把最轻的分给谁才能以最快的速度找到1号(使1号入度为0),并把当前最轻的分给1号。所以我们要由重的向轻的连边,然后从大到小每次把一个重量分给一个入度为0的点。这样我们就不用急于探求最小号。我们只需要一直给最大号附最大值,尽量不给小号赋值,这样自然而然就会把轻的重量留给小号。
注意重边。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #define ll long long using namespace std; int t,n,m,x,y,tot; int p[205][205],a[205][205],c[205],ru[205]; int head[205],Next[40005],to[40005]; void add(int x,int y) { tot++; Next[tot]=head[x]; to[tot]=y; head[x]=tot; } void tuopu() { int w=n; while(1) { int t=0,find=0; for(int i=n;i>=1;i--) if(ru[i]==0) { find=1; c[i]=w; w--; ru[i]--; for(int j=head[i];j!=-1;j=Next[j]) ru[to[j]]--; break; } if(!find) break; } for(int i=1;i<n;i++) printf("%d ",c[i]); printf("%d\n",c ); } int floyd() { for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(a[i][k]&&a[k][j]) a[i][j]=1; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(a[i][j]&&a[j][i]) return -1; return 0; } int main() { cin>>t; while(t--) { cin>>n>>m; tot=0; memset(p,0,sizeof(p)); memset(a,0,sizeof(a)); for(int i=1;i<=n;i++) { head[i]=-1; ru[i]=0; } for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); if(p[y][x]==0) { add(y,x); ru[x]++; } p[y][x]=1; a[y][x]=1; } if(floyd()==-1) printf("-1\n"); else tuopu(); } return 0; }
相关文章推荐
- Linux001
- OPenfire简介
- gulp+bower体系如何使用browserify调用npm模块
- 经验问题(一)
- 第一次机房收费系统--上机
- SQL笔记
- How to generate Hibernate mapping files & annotation with Hibernate Tools
- QT调试宏
- ThinkPHP教程_PHP框架之ThinkPHP(五)【连接数据库与主从数据库设置】
- Spark伪分布安装(依赖Hadoop)
- 前端工程师必须收藏的 JavaScript 资源大全
- Android使用DownloadManager下载文件
- linux中误删除程序包恢复示例 推荐
- 【转载】Unity 2D 开发(1)- 精灵打包
- 第1个python程序:打印
- 15个必须知道的chrome开发者技巧
- JavaScript函数(arguments,this)的理解
- bzoj1042: [HAOI2008]硬币购物
- SQL Server CONVERT() 函数
- 多进程和多线程的应用场景