2 1 1 2 2 2 1 2 2 1
1777 -1
刚开始还以为是带权并查集,迅速的敲完,然后就WA了。
后来测试了一组这样的数据: 4 4 1 2 2 3 1 4 3 4
发现出问题了,后来才开始学习拓扑排序。
这道题要注意图应该是有向图,从谁出发到谁应该处理好,弄不好就懵了。
要是找不出bug的情况,不如试试以下类型的数据:
①普通题目中的数据(废话)
②有独立点的数据:3 1 1 2 ———— 2665
③有环的数据(一种是无解的环,一种是有解的环):3 3 1 2 2 3 3 1 ———— -1
4 4 1 2 2 3 1 4 3 4 ———— 3558
代码如下:
#include <cstdio> #include <queue> #include <algorithm> #include <cstring> using namespace std; struct node { int from,to; //表示方向 }data[20022]; int n,m; long long ans; //int cost[10022]; //该点花费的钱数(为了计算下一个入度为0的节点) (好像这个多余了) int used[10022]; //是否遍历过 int in[10022]; int ach = 0; //已完成的节点数 bool flag; void init() { for (int i = 1 ; i <= n ; i++) { in[i] = 0; used[i] = 0; } ans = 0; flag = true; } void topo() { queue<int>q; ach = 0; //已完成的节点数 int s = 0; //花费,每进行一轮花费加1(很朴素的方法,但是有效) while (1) { int k = 0; for (int i = 1 ; i <= n ; i++) { if (!used[i] && in[i] == 0) { q.push(i); k = 1; ans += s; ach++; used[i] = 1; } } if (k == 0) break; //说明已经没有入度为0的点了 while (!q.empty()) { int tt = q.front(); q.pop(); for (int i = 1 ; i <= m ; i++) { if (data[i].from == tt && used[data[i].to] == 0) in[data[i].to]--; //把边减掉 } } s++; } } int main() { while (~scanf ("%d %d",&n,&m)) { init(); //代码太乱,初始化忘了 = = for (int i = 1 ; i <= m ; i++) { int t1,t2; scanf ("%d %d",&t1,&t2); //这里注意需要反向,应该是t2指向t1 data[i].from = t2; data[i].to = t1; in[t1]++; //表示入度 } topo(); if (ach != n) printf ("-1\n"); else { ans += n * 888; printf ("%lld\n",ans); } } return 0; }