HDU - 5413

題目鏈接:HDU - 5413


顯然,直接暴力維護拓撲序是不行的。

我們考慮從小到大遍歷拓撲序,然後對於當前遍歷的點,訪問他的前驅節點,並且從大到小訪問前驅點。

如果存在某個拓撲序大的點可以到這個點,那麼當前的這條邊就是冗餘邊。

因爲直接維護可達性複雜度太高,故用Bitset優化。


AC代碼:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=2e4+10;
int n,m,deg[N],res;
vector<int> g[N],v[N],ts;	bitset<N> bit[N];
void Top(){
	queue<int> q; for(int i=1;i<=n;i++)	if(!deg[i])	q.push(i); ts.clear();
	while(q.size()){
		int u=q.front();	q.pop();	ts.push_back(u);
		for(auto to:g[u]){
			if(--deg[to]==0)	q.push(to);	v[to].push_back(u);
		}
	}
}
inline void solve(){
	cin>>n>>m;	res=0;
	for(int i=1;i<=n;i++)	g[i].clear(),v[i].clear();
	for(int i=1,a,b;i<=m;i++)	scanf("%d %d",&a,&b),g[a].push_back(b),deg[b]++;
	Top();
	for(int i=1;i<=n;i++)	bit[i].reset(),bit[i].set(i);
	for(int i=0;i<n;i++){
		for(int j=v[ts[i]].size()-1;j>=0;j--){
			int to=v[ts[i]][j];
			if(bit[ts[i]][to])	res++;
			bit[ts[i]]|=bit[to];
		}
	}
	printf("%d\n",res);
}
signed main(){
	int T;	cin>>T;
	while(T--)	solve();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章