CF1815C 题解
思路
首先看到这种二元组的问题,可以先连边。在这个问题中是
可以思考什么时候数列无限长。猜测当有数在有向图上不能走到
若不是这种情况,则每个数都直接或间接被
注意,对于
为什么这样的构造满足要求呢?
- 对于
dis 较大的数连向dis 较小的数,一定有前者的dis 为后者的dis+1 ,那么在插入的过程中就能保证dis 较大的数相邻两个之间都有且仅有一个dis 较小的数。 - 对于
dis 相同的数有连接,因为每次插入的顺序是一样的,所以也可以保证。 - 对于
dis 较小的数连向dis 较大的数,可以发现每次插入dis 较大的数时一定有数在任意一对dis 较小的数中间,因此也能保证。可以手摸一下样例以保证完全理解。
不必用程序模拟这样的过程。手摸后可以发现,设
代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
vector<int> e1[1510];
queue<int> q;
int dis[1510];
vector<int> e2[1510];
int tot,ans[2000010];
int main()
{
int t; cin>>t; while(t--)
{
cin>>n>>m;
for(int i=1; i<=n; ++i) e1[i].clear();
for(int i=1; i<=m; ++i)
{
int u,v; cin>>u>>v;
e1[v].push_back(u);
}
memset(dis,0x3f,sizeof(dis));
dis[1]=0,q.push(1);
while(!q.empty())
{
int frn=q.front(); q.pop();
for(int v:e1[frn])
{
if(dis[v]>=1e9) dis[v]=dis[frn]+1,q.push(v);
}
}
bool flag=0;
for(int i=1; i<=n; ++i) flag|=(dis[i]>=1e9);
if(flag) { cout<<"INFINITE\n"; continue; }
cout<<"FINITE\n";
for(int i=1; i<=n; ++i) e2[i].clear();
for(int i=1; i<=n; ++i) e2[dis[i]].push_back(i);
tot=0;
for(int i=n; i>=1; --i) for(int j:e2[i]) ans[++tot]=j;
ans[++tot]=1;
for(int i=1; i<=n; ++i)
{
for(int j=n; j>=i; --j)
{
for(int k:e2[j]) ans[++tot]=k;
}
}
cout<<tot<<'\n';
for(int i=1; i<=tot; ++i) cout<<ans[i]<<' '; cout<<'\n';
}
return 0;
}