[传递闭包] P2881 [USACO07MAR]排名的牛Ranking the Cows
题意
FJ想按照奶牛产奶的能力给她们排序。
现在已知有\(N (1 \le N \le 10^3)\) 头奶牛。FJ通过比较,已经知道了 \(M (1 \le M \le 10^4)\) 对相对关系。
每一对关系表示为X Y
,意指X
的产奶能力强于Y
。
现在FJ想要知道,他至少还要调查多少对关系才能完成整个排序。
传递闭包
传递闭包指一个图上的点 \(x\),是否可以到达除了点 \(x\) 外的其他点。
传递闭包的储存形式类似邻接矩阵。
传递闭包的实现类似 Floyd
。
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (E[i][k] && E[k][j])
E[i][j] = 1;
具体说明可见 知乎——算法学习笔记(57): 传递闭包
Code
此题暴力使用传递闭包会 TLE
。
要使用 bitset
优化。
具体看代码。
const int N = 1005;
bitset<N> g[N];
int n,m;
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++) g[i][i] = 1;
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
g[u][v] = 1;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
if(g[i][k])
g[i] |= g[k];
int ans = 0;
for(int i=1;i<=n;i++)
ans += g[i].count();
cout<<n * (n - 1) / 2 - ans + n << endl;
return 0;
}