P2419 [USACO08JAN] Cow
这道题目虽然标签贴有拓扑排序的算法标签,但是因为题目说了前后不会有矛盾所以应该不需要使用拓扑排序来判断是否会有矛盾。
所以这题其实还是使用的是floyd,但是这题并不是利用floyd来求最短路,而是利用floyd来判断各点之间是否具有连通性,这也算是对floyd的妙用吧,举个例子假如有一组数据,1 4和4 6,在本题目中的意思是1排名高于4,4排名高于6所以可以推理得出1排名高于6,如果转换成图来看的话,其实是一个有向图,被指到的数字排名低于指他的数字,所以就是1指向4,4指向6,从而利用4这个中间点联通1和6,这一点契合floyd算法的特性,所以想到了使用floyd。
使用floyd得到各点之间是否有关系之后,我们就可以来思考一下满足什么条件能够确定一个点的排名,很容易想到判断出一个点的具体排名只要满足排在它前面的数字和后面的数字之和为n - 1就可以确定下来这个点的排名了。
//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize("Os")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("Og")
//#pragma GCC optimize("inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <ll , ll> pii;
typedef priority_queue <ll ,vector<ll> ,greater<ll> > xiao;
typedef priority_queue <ll ,vector<ll> ,less<ll> > da;
const int N=1e5 + 10,M = 0x3f3f3f3f;
const ull P = 131;
int g[105][105];
int n,m;
int num[105];
void floyd()
{
for(int k = 1 ; k <= n ; k++)
{
for(int i = 1 ; i <= n ; i++)
{
for(int j = 1 ; j <= n ; j++)
{
g[i][j] = min(g[i][j] , g[i][k] + g[k][j]);
}
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0),cout.tie(0);
cin>>n>>m;
memset(g , M , sizeof g); //全部初始化为最大值
for(int i = 1 ; i <= m ; i++)
{
int a,b;
cin>>a>>b;
g[a][b] = 1;
}
floyd();
for(int i = 1 ; i <= n ; i++)
{
for(int k = 1 ; k <= n ; k++)
{
if(g[i][k] != M) //将邻接矩阵前后两项都记录在num中
{
num[i]++;
num[k]++;
}
}
}
int ans = 0;
for(int i = 1 ; i <= n ; i++) //判断每个数字在确定下来的关系中是否出现次数达到nn - 1次
{
if(num[i] == n - 1)
{
ans++;
}
}
cout<<ans;
}