Description
xxxxxyt学姐经常一个人在家,难免会感到寂寞,于是学姐养了n只可爱的宠物,比
如皮皮虾、大蟒蛇、藏狐、安康鱼…但即便如此学姐还是感到无聊。突然有一天,学姐想到
了让宠物们互相对战的消遣方法(请不要给动物保护协会打电话!)。学姐让宠物们两两进
行对战,n*(n-1)/2场对战后,学姐得到了一张相生相克图,然后又根据自己的喜好,把
宠物们分成了一队与二队。就在队伍分好后,学姐的强迫症又犯了,她希望自己的两支队伍
都满足这样一个性质:存在某种排列,使得排在后面的宠物能够击败排在前面的所有宠物。
但学姐的懒惰大家都是知道的,所以她找到了你,希望你能告诉她这两支队伍是否均满足要
求,如果是,她还希望你告诉她最多可以从二队中抽出多少只宠物放在一队,使得两支队伍
仍然满足要求。努力解决问题吧,而xxxxxyt学姐,瘫躺。
Input
第一行输入两个数字n和m,分别表示学姐有n只宠物,其中被分到一队的宠物有m
只。
接下来n行每行n个数字,ai,j
表示第i只宠物是否能战胜第j只宠物,保证ai,i=0
且ai,j=!aj,i
。
接下来一行m个数字,表示有哪些宠物被分到了一队。
Output
如果两支队伍均不能让xxxxxyt满意,则输出“NO”;否则输出“YES”,并输出一个
最大的k,使得从二队中非任意地抽出k只宠物放入一队后,两支队伍仍然满足条件。详细
格式见样例输出。
Sample Input 1
3 2
0 1 1
0 0 1
0 0 0
3 1
Sample Output 1
YES 1
Sample Input 2
4 3
0 1 0 1
0 0 1 1
1 0 0 1
0 0 0 0
1 2 3
Sample Output 2
NO
Sample Input 3
4 2
0 1 0 1
0 0 1 1
1 0 0 1
0 0 0 0
1 2
Sample Output 3
YES 1
Hint
注意:
宠物们的实力是相对的,也就是可能会出现A战胜B,B战胜C,C又战胜A的
情况。
数据范围:
20%的数据1<=m<n<=10
60%的数据1<=m<n<=100
xxxxxyt学姐经常一个人在家,难免会感到寂寞,于是学姐养了n只可爱的宠物,比
如皮皮虾、大蟒蛇、藏狐、安康鱼…但即便如此学姐还是感到无聊。突然有一天,学姐想到
了让宠物们互相对战的消遣方法(请不要给动物保护协会打电话!)。学姐让宠物们两两进
行对战,n*(n-1)/2场对战后,学姐得到了一张相生相克图,然后又根据自己的喜好,把
宠物们分成了一队与二队。就在队伍分好后,学姐的强迫症又犯了,她希望自己的两支队伍
都满足这样一个性质:存在某种排列,使得排在后面的宠物能够击败排在前面的所有宠物。
但学姐的懒惰大家都是知道的,所以她找到了你,希望你能告诉她这两支队伍是否均满足要
求,如果是,她还希望你告诉她最多可以从二队中抽出多少只宠物放在一队,使得两支队伍
仍然满足要求。努力解决问题吧,而xxxxxyt学姐,瘫躺。
Input
第一行输入两个数字n和m,分别表示学姐有n只宠物,其中被分到一队的宠物有m
只。
接下来n行每行n个数字,ai,j
表示第i只宠物是否能战胜第j只宠物,保证ai,i=0
且ai,j=!aj,i
。
接下来一行m个数字,表示有哪些宠物被分到了一队。
Output
如果两支队伍均不能让xxxxxyt满意,则输出“NO”;否则输出“YES”,并输出一个
最大的k,使得从二队中非任意地抽出k只宠物放入一队后,两支队伍仍然满足条件。详细
格式见样例输出。
Sample Input 1
3 2
0 1 1
0 0 1
0 0 0
3 1
Sample Output 1
YES 1
Sample Input 2
4 3
0 1 0 1
0 0 1 1
1 0 0 1
0 0 0 0
1 2 3
Sample Output 2
NO
Sample Input 3
4 2
0 1 0 1
0 0 1 1
1 0 0 1
0 0 0 0
1 2
Sample Output 3
YES 1
Hint
注意:
宠物们的实力是相对的,也就是可能会出现A战胜B,B战胜C,C又战胜A的
情况。
数据范围:
20%的数据1<=m<n<=10
60%的数据1<=m<n<=100
100%的数据1<=m<n<=100
显然一个序列的规则是满足拓扑排序的,故可以用拓扑排序check,且合法的排列方法唯一,即拓扑序。现在问题就变成了有一队二队两条有向链,问二队链中至多有多少个可以合法地插入一队链,用f[i][j]表示一队链讨论到第i个二队
链讨论到第j个,二队链中至多插入f[i][j]个,转移为:
f[i][j]=max{f[i-1][j],f[i][j-1],f[i][j-1]+1(二队中第j个宠物弱于一队中1...i强于i+1...m)}
直接转移暴力判断复杂度为O(n^3)
因此对二队中第j个宠物是否弱于一队中1...i强于i+1...m进行预处理,便可在复杂度O(n2)下得到答案
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=1005,inf=1e9;
inline void _read(int &x){
char t=getchar();bool sign=true;
while(t<'0'||t>'9')
{if(t=='-')sign=false;t=getchar();}
for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
if(!sign)x=-x;
}
int n,m,type[maxn],du[maxn],f[maxn][maxn];
int s1[maxn],s2[maxn],l[maxn][maxn],r[maxn][maxn];
int map[maxn][maxn];
bool topsort(int s[],int kind,int sum){
queue<int>q;
int i,j,t=0;
bool mark[maxn];
memset(mark,0,sizeof(mark));
for(i=1;i<=n+m;i++)
if(type[i]==kind&&(!du[i])){
q.push(i);
s[++t]=i;
mark[i]=1;
}
while(q.size()){
int x=q.front();q.pop();
for(i=1;i<=n+m;i++)
if(!mark[i]&&type[i]==kind){
if(map[x][i]&&du[i])du[i]--;
if(!du[i]){
q.push(i);
mark[i]=1;
s[++t]=i;
}
}
}
return t==sum;
}
int main(){
int i,j,x;
_read(n);_read(m);
for(i=1;i<=n;i++){
for(j=1;j<=n;j++)_read(map[i][j]);
type[i]=2;
}
for(i=1;i<=m;i++){
_read(x);
type[x]=1;
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(type[i]==type[j]&&map[i][j])du[j]++;
n-=m;swap(n,m);
if(!topsort(s1,1,n)||(!topsort(s2,2,m))){
puts("NO");
return 0;
}
for(j=1;j<=m;j++){
l[0][j]=r[n+1][j]=1;
for(i=1;i<=n;i++)l[i][j]= map[s1[i]][s2[j]]&&l[i-1][j];
for(i=n;i;i--)r[i][j]= map[s2[j]][s1[i]]&&r[i+1][j];
}
for(i=0;i<=n;i++)
for(j=0;j<=m;j++){
if(j)f[i][j]=max(f[i][j],f[i][j-1]);
if(i)f[i][j]=max(f[i][j],f[i-1][j]);
if(j&&l[i][j]&&r[i+1][j])f[i][j]=max(f[i][j],f[i][j-1]+1);
}
cout<<"YES"<<" "<<f[n][m];
}