NKOI 3747 宠物

来源:互联网 发布:锵锵三人行9月11 知乎 编辑:程序博客网 时间:2024/04/28 03:24
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

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];}


0 0
原创粉丝点击