求问本题边界情况
  • 板块CF1815C Between
  • 楼主Milky_Cat
  • 当前回复2
  • 已保存回复2
  • 发布时间2024/11/26 12:24
  • 上次更新2024/11/26 16:46:49
查看原帖
求问本题边界情况
906320
Milky_Cat楼主2024/11/26 12:24

做法:拓扑排序+dp。

若存在一个 (ai,bi)(a_i,b_i) 的二元组,建一条 biaib_i \rightarrow a_i 的有向边。记 fif_i 表示数 ii 的出现次数,则有 faifbi+1f_{a_i} \leq f_{b_i}+1,对于每个 aia_i 求出最小的 fbi+1f_{b_i}+1 即可。

注意到由于环和不联通有一些点没被更新到。没被更新到的点一定可以无限放,这时输出 INFINITE

然后交上去,显示我把 FINITE 判成了 INFINITE

#include<bits/stdc++.h>
using namespace std;
int t;
int n, m, deg[2005], f[2005];
vector<int> G[2005];
queue<int> q;
struct node{
	int nf, f, vl;
	bool operator < (node b) const {
		if (this->nf != b.nf)
			return this->nf < b.nf;
		else
			return this->f > b.f;
	}
};
priority_queue<node> Q;
bool topo(){
	f[1] = 1;
	q.push(1);
	while (!q.empty()){
		int u = q.front();
		q.pop();
		for (auto v : G[u]){
			if (f[v] == -1 || f[v] > f[u] + 1)
				f[v] = f[u] + 1;
			deg[v]--;
			if (!deg[v])
				q.push(v);
		}
	}
	for (int i = 1; i <= n; i++)
		if (f[i] == -1)
			return 0;
	return 1;
		
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while (t--){
		cin >> n >> m;
		for (int i = 1; i <= n; i++){
			f[i] = -1;
			deg[i] = 0;
			G[i].clear();
		}
		for (int i = 1; i <= m; i++){
			int u, v;
			cin >> u >> v;
			G[v].push_back(u);
			deg[u]++;
		}
		bool chk = topo();
		if (chk){
			cout << "FINITE\n";
			int ans = 0;
			for (int i = 1; i <= n; i++){
				Q.push({f[i], f[i], i});
				ans += f[i];
			}
			cout << ans << "\n";
			while (!Q.empty()){
				node u = Q.top();
				Q.pop();
				if (u.nf == 1){
					cout << u.vl << " ";
				}else{
					cout << u.vl << " ";
					u.nf--;
					Q.push(u);
				}
			}
			cout << "\n";
		}else
			cout << "INFINITE\n";
	}
	return 0;
}

15min 写完,调到 1h 没调出来,还有必要学下去吗。

2024/11/26 12:24
加载中...