确定比赛名次
题目传送:HDU – 1285 – 确定比赛名次
思路:拓扑排序
AC代码①(遍历找最小字典序):
#include <map>
#include <set>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define INF 0x7fffffff
using namespace std;
int n, m;
int mp[505][505];
int deg[505];
void topo_sort() {
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= n; j ++) {
if(deg[j] == 0) {
deg[j] --;
if(i != n) cout << j << " ";
else cout << j << endl;
for(int k = 1; k <= n; k ++) {
if(mp[j][k] == 1) {
deg[k] --;
}
}
break;
}
}
}
}
int main() {
while(scanf("%d %d", &n, &m) != EOF) {
memset(mp, 0, sizeof(mp));
memset(deg, 0, sizeof(deg));
int u, v;
for(int i = 0; i < m; i ++) {
scanf("%d %d", &u, &v);
if(!mp[u][v]) {//注意这里一个队可能赢一个队多场
mp[u][v] = 1;
deg[v] ++;
}
}
topo_sort();
}
return 0;
}
AC代码②(优先队列找最小字典序):
#include <map>
#include <set>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define INF 0x7fffffff
using namespace std;
int n, m;
int deg[505];
int mp[505][505];
int topo[505];
int cnt;
void bfs() {
priority_queue<int, vector<int>, greater<int> > q;//最小堆,因为默认为最大堆,可以通过greater来设置为最小堆
for(int i = 1; i <= n; i ++) {
if(deg[i] == 0) {
q.push(i);
}
}
while(!q.empty()) {
int t = q.top();
q.pop();
topo[cnt ++] = t;
for(int i = 1; i <= n; i ++) {
if(mp[t][i]) {
deg[i] --;
if(deg[i] == 0) q.push(i);
mp[t][i] = 0;//删边
}
}
}
}
int main() {
while(scanf("%d %d", &n, &m) != EOF) {
memset(deg, 0, sizeof(deg));
int u, v;
for(int i = 0; i < m; i ++) {
scanf("%d %d", &u, &v);
if(!mp[u][v]) {//注意这里一个队可能赢一个队多场
mp[u][v] = 1;
deg[v] ++;
}
}
cnt = 0;
bfs();
for(int i = 0; i < cnt - 1; i ++) {
printf("%d ", topo[i]);
}
printf("%d\n", topo[cnt - 1]);
}
return 0;
}
产生冠军
题目传送:HDU – 2094 – 产生冠军
思路:因为只要确定是否产生冠军,根据题意可以得知当且仅当入度为0的只有一个时可以产生冠军,可以用map来映射存储的人的名字
AC代码:
#include <map>
#include <set>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define INF 0x7fffffff
using namespace std;
map<string, int> mp;
int deg[1005];
int cnt;
int n;
int main() {
while(scanf("%d", &n) != EOF) {
if(n == 0) break;
memset(deg, 0, sizeof(deg));
cnt = 1;
mp.clear();
string s1, s2;
for(int i = 0; i < n; i ++) {
cin >> s1 >> s2;
// cout << s1 << " " << s2 << endl;
if(mp.find(s1) == mp.end()) {
mp[s1] = cnt ++;
}
if(mp.find(s2) == mp.end()) {
mp[s2] = cnt ++;
}
int t1 = mp[s1];
int t2 = mp[s2];
deg[mp[s2]] ++;
}
int sum = 0;
for(int i = 1; i < cnt; i ++) {
if(deg[i] == 0) {
sum ++;
}
}
if(sum == 1) {
printf("Yes\n");
}
else printf("No\n");
}
return 0;
}
Reward
题目传送:HDU – 2647 – Reward
思路:拓扑排序,倒着往前推,即把u->v的边在建图的时候看成v->u。
AC代码:
#include <map>
#include <set>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define INF 0x7fffffff
using namespace std;
const int maxn = 10005;
int n, m;
int sum, ans;
struct node {
int x, p;
node() {}
node(int _x, int _p) : x(_x), p(_p) {}
};
vector<int> mp[maxn];
int deg[maxn];
void topo() {
queue<node> que;
for(int i = 1; i <=n; i ++) {
if(deg[i] == 0) {
que.push(node(i, 888));
sum --;
ans += 888;
}
}
while(!que.empty()) {
node t = que.front();
que.pop();
int d = mp[t.x].size();
for(int i = 0; i < d; i ++) {
deg[mp[t.x][i]] --;
if(deg[mp[t.x][i]] == 0) {
sum --;
ans += t.p + 1;
que.push(node(mp[t.x][i], t.p + 1));
}
}
}
}
int main() {
while(scanf("%d %d", &n, &m) != EOF) {
memset(deg, 0, sizeof(deg));
for(int i = 1; i <= n; i ++) {//居然忘记初始化WA了,╮(╯▽╰)╭
mp[i].clear();
}
int u, v;
for(int i = 0; i < m; i ++) {
scanf("%d %d", &u, &v);
mp[v].push_back(u);
deg[u] ++;
}
sum = n;
ans = 0;
topo();
if(sum <= 0) {
printf("%d\n", ans);
}
else printf("-1\n");
}
return 0;
}