<题面>
一个蒟蒻的痛苦一天
在今天的节目集训中,麦蒙将带领大家学习9种错误的解题策略
$15\%$算法(看两个就往下走吧)
1> puts("Impossible!");
不解释(话说多测输出这个有分真是奇迹)(这个过不了样例了)
2>DFS无优化贪心法
随后,我想到,如果用dfs处理每一部分就可以将一些小的菜肴优先纳入考虑(样例也能过)
当然,这个也有错误,是贪心的目光短浅导致的,比如
1 5 4 4 1 5 1 3 4 2 5
会因为去搜了$4$而搜不到$2$,错了~
3>DFS快排法(动态申请数组内存)
这个地方主要提一点:一个巨大的数组存下一个目标会RE局部变量开不了太大(如果用全局变量,一定崩),所以先用全局暂存,再用记录的数量K开数组,但是还是WA(思路不对)(还能过样例)
这是个技巧
1 int lins[P]; 2 bool dfs(int k) { 3 is_v[k] = 1; 4 int j = 0; 5 for (int i = fl[k]; i != -1; i = rs[i].next) { 6 if ((is_v[rs[i].t]) && (!is_del[rs[i].t])) 7 return 1; 8 if (!is_v[rs[i].t]) { 9 lins[j] = i; 10 j++; 11 } 12 } 13 int dat[j];//在这里开了数组 14 for (int i = 0; i < j; i++) dat[i] = lins[i]; 15 sort(dat + 0, dat + j, Mcmp); // cout<<"Dat:"; 16 // for(int i=0;i<j;i++)cout<<rs[dat[i]].t<<" ";cout<<endl; 17 for (int i = 0; i < j; i++) { // cout<<"Willgo:"<<rs[dat[i]].t<<endl; 18 if (!is_v[rs[dat[i]].t]) { // puts("Cango!!"); 19 if (dfs(rs[dat[i]].t)) { 20 return 1; 21 } 22 } 23 } 24 // cout<<"k<"<<k<<endl; 25 is_del[k] = 1; 26 ansadd(k); // 统计答案 27 return 0; 28 }
4>DFS判环+拓扑排序法
发现上面的问题,马上着手改,在DFS判环之后,进行拓扑,又WA了几次(诶样例什么状态)
5>DFS分离+部分图拓扑排序
其实5,6是一样的,都是把一小部分里可以拓扑的点记录,然后拓扑解决这一小块(保证了分离出来的点的优先),但是在拓扑的过程中不能确保里面具体的点的顺序,只是用的DFS还是BFS的区别
(已经不调样例了)
6>BFS分离+部分图拓扑排序
7>类迪杰斯特拉法
防止递归,用一个循环改了(但是在写的过程中真的很像迪杰),然后再拓扑。(手模样例)
8>堆优化的分离拓扑
蒟蒻听说用堆优化,于是信心满满(?)的在自己的拓扑中引进了堆,但是无力回天(方法不对啊)(样例真的水)
9>倒序思路的拓扑
这个最好想了,我直接反向建图,一般拓扑,最后反向输出就好了(样例能过)
但是这种贪心与原来的普通拓扑是一致的,有错误,不能确保编号小的菜肴优先级
这个其实很接近正解了,也许是我拓扑错了?
以下是正解:
想一下为什么建正图,直接找小编号会错。
因为我们不能首先保证小号节点优先出现,当前入度为0的点指向是不确定的
换个角度想,如果我们能确保大号节点靠后出现,小号节点自然尽量考前,这时就不必担心大号节点之下是不是更大的节点了,是不是都不影响(是就删它,不是就换一个,因为已经删了的点和现在的点有限制关系,不用担心会出错)
用堆优化这个过程,自然是大根堆了(叫大顶堆也好听;-))
1 #include <iostream> 2 #include <cstdio> 3 #include <queue> 4 #include <cstring> 5 #define N 101101 6 using namespace std; 7 struct SR { 8 int f, t, next; 9 } rs[N]; 10 int ecn = 0, fl[N], deg[N]; 11 void add(int f, int t) { 12 ecn++; 13 rs[ecn].f = f; 14 rs[ecn].t = t; 15 rs[ecn].next = fl[f]; 16 fl[f] = ecn; 17 } 18 priority_queue<int, vector<int>, less<int> > q; 19 int pn, en; 20 int ans[N], ant = 0; 21 void prerun() { 22 ant = ecn = 0; 23 memset(fl, -1, sizeof fl); 24 memset(deg, 0, sizeof deg); 25 while (!q.empty()) q.pop(); 26 memset(rs, 0, sizeof rs); 27 } 28 void addans(int k) { 29 ans[ant] = k; 30 ant++; 31 } 32 bool check() { 33 for (int i = 1; i <= pn; i++) { 34 if (deg[i] != 0) 35 return 1; 36 } 37 return 0; 38 } 39 void top() { 40 for (int i = 1; i <= pn; i++) { 41 if (deg[i] == 0) 42 q.push(i); 43 } 44 // debug(q); 45 while (!q.empty()) { 46 int f = q.top(); 47 q.pop(); // cout<<"Got"<<f<<endl; 48 for (int i = fl[f]; i != -1; i = rs[i].next) { 49 deg[rs[i].t]--; 50 if (deg[rs[i].t] == 0) { 51 q.push(rs[i].t); // cout<<"Wii"<<rs[i].t<<endl; 52 } 53 } 54 addans(f); 55 } 56 if (check()) { 57 puts("Impossible!"); 58 return; 59 } 60 for (int i = ant - 1; i >= 0; i--) { 61 printf("%d ", ans[i]); 62 } 63 puts(""); 64 } 65 int main() { 66 int T, a, b; 67 cin >> T; 68 while (T--) { 69 prerun(); 70 scanf("%d%d", &pn, &en); 71 for (int i = 1; i <= en; i++) { 72 scanf("%d%d", &a, &b); 73 add(b, a); 74 deg[a]++; 75 } 76 top(); 77 } 78 return 0; 79 }