Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 13776 | Accepted: 3983 |
Description
Windy has N balls of distinct weights from 1 unit to N units. Now he tries to label them with 1 toN in such a way that:
- No two balls share the same label.
- The labeling satisfies several constrains like "The ball labeled with a is lighter than the one labeled withb".
Can you help windy to find a solution?
Input
The first line of input is the number of test case. The first line of each test case contains two integers,N (1 ≤ N ≤ 200) and M (0 ≤ M ≤ 40,000). The nextM line each contain two integers a and b indicating the ball labeled witha must be lighter than the one labeled with b. (1 ≤ a, b ≤N) There is a blank line before each test case.
Output
For each test case output on a single line the balls' weights from label 1 to labelN. If several solutions exist, you should output the one with the smallest weight for label 1, then with the smallest weight for label 2, then with the smallest weight for label 3 and so on... If no solution exists, output -1 instead.
Sample Input
5 4 0 4 1 1 1 4 2 1 2 2 1 4 1 2 1 4 1 3 2
Sample Output
1 2 3 4 -1 -1 2 1 3 4 1 3 2 4
Source
题目大意:
有N个重量不一样的球,重量为1~N,有N个盒子,标号为1~N,给出M组大小关系,a b表示标号为a的盒子放的球比标号为b的盒子放的球轻。从左到右输出每个盒子里的球的重量,而且前面的盒子里的球要尽可能的小。(注意是按照盒子的顺序输入里面的球,不是输出各个球所在的盒子!!!不知道自己WA哪的同学好好读一下题)
解题思路:
这题确实题意杀,思维有点绕,开始读错题了WA了好几发。
我们每个盒子之间的约束条件,如果直接拓扑排序得到的是怎么摆放盒子,使它们内部的球为1~N,然而这并不是题目问的。
由于要求字典序最小,我们要让第一个盒子装尽可能轻的球,然而根据题目条件给盒子找球并不好实现。所以我们可以从相反的角度思考一下:我们只要让重的球尽可能放在后面就可以保证字典序最小,这样就转化成了给球找盒子,直接贪心地拓扑排序即可。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=200+3;
int N,M;
bool used[maxn];//是否每个盒子是否已经放球的
vector<int> G[maxn];//入边表
int out[maxn],ans[maxn];
bool toposort()
{
for(int i=N;i>0;--i)//先分配重的球
{
int select=-1;
for(int j=N;j>0;--j)//优先放右边的盒子
if(!used[j]&&!out[j])
{
select=j;
break;
}
if(select==-1)//存在环,无解
return false;
for(int j=0;j<G[select].size();++j)
--out[G[select][j]];
used[select]=true;
ans[select]=i;
}
return true;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(used,0,sizeof used);
memset(out,0,sizeof out);
scanf("%d%d",&N,&M);
for(int i=1;i<=N;++i)
G[i].clear();
for(int i=0;i<M;++i)
{
int a,b;
scanf("%d%d",&a,&b);
G[b].push_back(a);//入边表
++out[a];
}
if(toposort())
for(int i=1;i<=N;++i)
printf("%d%c",ans[i],i==N?'\n':' ');
else puts("-1");
}
return 0;
}