题解思路:我们把数组这些元素看成点然后两个点之间一条有向边的前提为i<j,a[i]<a[j],那么这样题目就变成了找两条路径把所有的点都盖上去那么就是有向图的最小路径覆盖问题,判断路径数是否小于2
#include<bits/stdc++.h>
using namespace std;
const int mx = 2e3+5;
const int inf = 0x3f3f3f3f;
int dx[mx];
int dy[mx];
int x[mx];
int y[mx];
bool vis[mx];
int a[mx];
int dis;
int n;
bool search(){
dis = inf;
memset(dx,0,sizeof(dx));
memset(dy,0,sizeof(dy));
queue<int>q;
for(int i = 1; i <= n; i++)
if(!x[i]){
dx[i] = 1;
q.push(i);
}
while(!q.empty()){
int u = q.front();
q.pop();
if(dx[u]>=dis)
continue;
for(int i = u+1; i <= n; i++){
if(a[i]>a[u]&&dy[i]==0){
dy[i] = dx[u]+1;
if(y[i]) {dx[y[i]]=dy[i]+1,q.push(y[i]);}
else dis = dy[i];
}
}
}
return dis!=inf;
}
bool find(int u){
for(int i = u+1; i <= n; i++)
if(a[u]<a[i]&&dx[u]+1==dy[i]&&!vis[i]){
vis[i] = 1;
if(y[i]==0||find(y[i])){
y[i] = u;
x[u] = i;
return true;
}
}
return false;
}
int km(){
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
int ans = 0;
while(search()){
memset(vis,0,sizeof(vis));
for(int i = 1; i <= n; i++)
if(!x[i]&&find(i))
ans++;
}
return ans;
}
int main(){
//freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i = 1; i <= n; i++)
scanf("%d",&a[i]);
if(km()>=n-2)
puts("Yes!");
else
puts("No!");
}
return 0;
}