Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 9385 | Accepted: 2549 |
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 integersa and b indicating the ball labeled witha must be lighter than the one labeled withb. (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
这道题目需要认真读题。
题目需要求出的是 编号1-n的球的重量值。而且要求那个字典序最小的。
我们用拓扑排序的算法,需要让编号小的球尽可能往前排(获得较小的weight)。
但是如果每一步都去贪心,则会wa。因为 1<3 4 < 2 这种情况,会贪心出 1, 3, 4, 2 这个非最优解。(最优解应该是1,4,2,3)。因为当前贪心最小的球,并不能保证全局最小的球往前排。
因为1342对应的答案是1423 , 而 1423对应的答案是1324。这里是一个陷阱。所以需要认真读题。
因此我们反过来建图,每一步都选编号最大的那个求放到最后。(因此改用stack数据结构)
提交记录:
1. WA 因为没有看到题目中求的是 编号从1-n的球的重量!!! 需要做一个转化。
2. WA 因为没有考虑到贪心的错误。需要 反向建图。
3. AC
#include
#include
#include
#include
#include
#include
#include
#define MAXN 210 using namespace std; int n, m; int graph[MAXN][MAXN]; stack
result_q; int judge() { int graph1[MAXN][MAXN]; memcpy(graph1, graph, sizeof(graph)); int i, j; int out[MAXN] = {0}; for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (graph1[i][j] == 1) { out[i] ++; } } } int k; stack
q; int flag = 0; for (k = 0; k < n; ) { queue
du; for (i = n-1; i >= 0; i--) { if (out[i] == 0) { du.push(i); } } if (du.size() == 0) return 2; //没有找到入度为0的点,说明有环。高优先级判断 while (!du.empty()) { i = du.front(); du.pop(); k++; q.push(i); for (int j = 0; j < n; j++) { if (graph1[j][i]) { out[j]--; //减少指向它的结点的入度 graph1[j][i] = 0; //删除指向它的边 } } out[i] = -1; break; } } result_q = q; return 1; } int main() { int t; cin >> t; while (t--) { cin >> n >> m; int i, j; int left, right; memset(graph, 0, sizeof(graph)); int flag = 0; for (i = 1; i <= m; i++) { cin >> left >> right; graph[left-1][right-1] = 1; } flag = judge(); if (flag == 1) { int o = 0; int w = 1; int record[MAXN] = {0}; while (!result_q.empty()) { int a = result_q.top(); result_q.pop(); record[a] = w; w++; } for (i = 0; i < n; i++) { if (o != 0) cout << " "; o = 1; cout << (record[i]); } cout << endl; } else if (flag == 2) { cout << -1 << endl; } } return 0; }