产生冠军

来源:互联网 发布:seo好找工作吗 编辑:程序博客网 时间:2024/04/29 05:36

题目网址:产生冠军

题目存在两个易错点,我也是改了很久才发现的,都在代码中注释出来了,第一处就是map忘记清空,第二个就是对于题目所给的案例二,考虑不够充分,案例二虽然满足拓扑排序,但是无法产生冠军,因为最开始入度为0的点有两个,那么这两个人是无法区分出冠军的!(a和d是无法判断谁是冠军的,但是如果按照常规的求解拓扑序列的算法来求,那么输出的肯定是yes,拓扑序列看得是是否是无环图)。修改的方法就是初始入度为0的点入栈,判断栈内元素的个数,如果大于1,那么就是输出no,剩下的不要判断了!

#include<iostream>#include<queue>#include<vector>#include<map>#include<string>using namespace std;vector<int> edge[1001];queue<int> q;map<string, int> m;//表示每一个人的名字和他的编号的对应string str1, str2;//表示两组人的int indegree[1001];int main(){int n;while (cin >> n&&n){int cnt = 0;//表示参赛选手的人数for (int i = 0; i < 1001; i++){//初始化,不可少edge[i].clear();indegree[i] = 0;}m.clear();//易错点,容易遗漏for (int i = 0; i < n; i++){cin >> str1 >> str2;int a, b;//a和b分别是用来保存输入的两人的编号if (m.find(str1) == m.end()){//没有查找到,则插入m中m.insert(make_pair(str1, cnt));a = cnt;cnt++;}else{a = m.find(str1)->second;}if (m.find(str2) == m.end()){m.insert(make_pair(str2, cnt));b = cnt;cnt++;}else{b = m.find(str2)->second;}edge[a].push_back(b);indegree[b]++;}//cout << cnt << endl;/*map<string, int>::iterator it = m.begin();for (; it != m.end(); it++){cout << it->first << ' ' << it->second << endl;}*/while (!q.empty())q.pop();for (int i = 0; i < cnt; i++){if (indegree[i] == 0)q.push(i);}if (q.size() != 1){//这个也是易错点,如果没有这个,第二个案例就是yes,必须只能有一个冠军cout << "No" << endl;continue;}int ans = 0;while (!q.empty()){int now = q.front();q.pop();ans++;for (int j = 0; j < edge[now].size(); j++){indegree[edge[now][j]]--;if (indegree[edge[now][j]] == 0)q.push(edge[now][j]);}}if (ans == cnt)cout << "Yes" << endl;elsecout << "No" << endl;}return 0;}