题意:给你一个n*n的矩阵,分成两部分,记为T1,T2,
如果两部分都是一个竞赛图,那么T2最多能给T1多少个点,使得给完之后的两个图仍然是竞赛图
思路:首先可以根据拓扑排序分别判断每一个图是不是一个合法的图,即为T1,T2
如果都是合法的话,把T2中的每个点都尝试插入到T1中,如果能成功,显然位置是唯一的,
那么我们只要对T2中的点的位置做一个最长不下降子序列
#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
int mp[maxn][maxn],vis[maxn],degree[maxn],Vis[maxn];
int a[maxn],LIS[maxn],b[maxn],num[maxn],n;
bool solve(int x[],int flag,int m){
memset(degree,0,sizeof(degree));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(mp[i][j]==1&&vis[i]==flag&&vis[j]==flag)
degree[j]++;
queue<int>Q;
int cnt=0,Count=0;
for(int i=1;i<=n;i++)
if(vis[i]==flag&°ree[i]==0)
Q.push(i),Vis[i]=1,x[++cnt]=i;
while(!Q.empty()){
if(Q.size()>1)
return false;
int u=Q.front();
Q.pop();
Count++;
for(int i=1;i<=n;i++)
if(mp[u][i]==1&&vis[i]==flag&&Vis[i]==0){
degree[i]--;
if(degree[i]==0)
Q.push(i),Vis[i]=1,x[++cnt]=i;
}
}
if(Count!=m)
return false;
return true;
}
int read(){
char ch=getchar(),last=' ';
while(ch<'0' || ch>'9')last=ch,ch=getchar();
int ans=0;
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans;
return ans;
}
char str[40000];
int main(){
int m,x;
freopen("1003.in","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF){
if(n==0&&m==0)
break;
memset(vis,0,sizeof(vis));
memset(Vis,0,sizeof(Vis));
getchar();
for(int i=1;i<=n;i++){
gets(str);
for(int j=1;j<=n;++j)
mp[i][j]=str[j-1<<1]-'0';
}
for(int i=1;i<=m;i++)
x=read(),vis[x]=1;
if(!solve(a,1,m) || !solve(b,0,n-m))
printf("NO\n");
else{
memset(num,0,sizeof(num));
for(int i=1;i<=n-m;i++) //对于T2中的每个点
for(int j=1;j<=m;j++){
if(mp[ a[j] ][ b[i] ])
num[i]=j;
else{
int flag=1;
for(int k=j;k<=m;k++)
if(!mp[ b[i] ][ a[k] ])
flag=0;
if(flag==0)
num[i]=-1;
break;
}
}
int ans=0;
for(int i=1;i<=n-m;i++){
if(num[i]==-1)
LIS[i]=0;
else{
LIS[i]=1;
for(int j=1;j<i;j++)
if(num[i]>=num[j])
LIS[i]=max(LIS[i],LIS[j]+1);
}
ans=max(ans,LIS[i]);
}
printf("YES %d\n",ans);
}
}
return 0;
}