做法:拓扑排序+dp。
若存在一个 (ai,bi) 的二元组,建一条 bi→ai 的有向边。记 fi 表示数 i 的出现次数,则有 fai≤fbi+1,对于每个 ai 求出最小的 fbi+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 没调出来,还有必要学下去吗。