1. 程式人生 > 其它 >[傳遞閉包] P2881 [USACO07MAR]排名的牛Ranking the Cows

[傳遞閉包] P2881 [USACO07MAR]排名的牛Ranking the Cows

P2881 [USACO07MAR]Ranking the Cows G 傳遞閉包 + bitset 優化

題意

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;
}