题目链接:[POJ 3660]Cow Contest[DFS]
题意分析:
给出N头奶牛,和奶牛间的M个关系,每个关系描述为 a, b 代表a能力比b强,问:给出这M个关系,你能准确确定多少只奶牛的能力排名。
解题思路:
确定奶牛排名,那么,知道它前面有多少比它强,后面有多少比他弱,加起来的和如果等于 n - 1,那么这头奶牛的排名也就确定了。
个人感受:
首先脑袋中飞出了拓扑排序,然并卵。然后就想到了怎么确定排名,就想到了上面的解题思路了。dfs求的那一段花了不少时间,想着优化,结果证实还是一个个统计不会错。
网上还有floyd的做法,这里就不赘述了。也算是给题解添了其它版本XD。
具体代码如下:
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int MAXN = 111;
vector<int> G[MAXN], V[MAXN];
int cnt1[MAXN], cnt2[MAXN]; // cnt1:有多少点比该点弱(包括本身) cnt2:有多少点比该点强(包括本身)
bool vis[MAXN];
int dfs1(int x)
{
int ret = 1;
if (vis[x]) return 0;
vis[x] = 1;
if (!G[x].size()) return 1;
for (int i = 0; i < G[x].size(); ++i)
{
int to = G[x][i];
ret += dfs1(to);
}
return ret;
}
int dfs2(int x)
{
int ret = 1;
if (vis[x]) return 0;
vis[x] = 1;
if (!V[x].size()) return 1;
for (int i = 0; i < V[x].size(); ++i)
{
int to = V[x][i];
ret += dfs2(to);
}
return ret;
}
int main()
{
int n, m, a, b; scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) cnt1[i] = cnt2[i] = 1;
while (m --)
{
scanf("%d%d", &a, &b);
G[a].push_back(b);
V[b].push_back(a);
}
for (int i = 1; i <= n; ++i)
{
memset(vis, 0, sizeof vis);
cnt1[i] = dfs1(i);
}
for (int i = 1; i <= n; ++i)
{
memset(vis, 0, sizeof vis);
cnt2[i] = dfs2(i);
}
int ans = 0;
for (int i = 1; i <= n; ++i)
{
//cout << i << ": " << cnt1[i] << ' ' << cnt2[i] << endl;
if (cnt1[i] + cnt2[i] - 1 == n) // 因为包括本身,所以多统计了一次
++ans;
}
printf("%d\n", ans);
return 0;
}