PETS

问题:
xxxxxyt学姐经常一个人在家,难免会感到寂寞,于是学姐养了n只可爱的宠物,比如皮皮虾、大蟒蛇、藏狐、安康鱼…但即便如此学姐还是感到无聊。突然有一天,学姐想到了让宠物们互相对战的消遣方法(请不要给动物保护协会打电话!)。学姐让宠物们两两进行对战,n*(n-1)/2场对战后,学姐得到了一张相生相克图,然后又根据自己的喜好,把宠物们分成了一队与二队。就在队伍分好后,学姐的强迫症又犯了,她希望自己的两支队伍都满足这样一个性质:存在某种排列,使得排在后面的宠物能够击败排在前面的所有宠物。但学姐的懒惰大家都是知道的,所以她找到了你,希望你能告诉她这两支队伍是否均满足要求,如果是,她还希望你告诉她最多可以从二队中抽出多少只宠物放在一队,使得两支队伍仍然满足要求。努力解决问题吧,而xxxxxyt学姐,瘫躺。
输入格式
第一行输入两个数字n和m,分别表示学姐有n只宠物,其中被分到一队的宠物有m只。
接下来n行每行n个数字,ai,j表示第i只宠物是否能战胜第j只宠物,保证ai,i=0且ai,j==!aj,i。
接下来一行m个数字,表示有哪些宠物被分到了一队。
输出格式
如果两支队伍均不能让xxxxxyt满意,则输出“NO”;否则输出“YES”,并输出一个最大的k,使得从二队中非任意地抽出k只宠物放入一队后,两支队伍仍然满足条件。详细格式见样例输出。
解:
此题不能用tarjan贪心 可能出现环套环的情况
注意到这是一个有向完全图 所以top序列在不存在环的情况下一定是唯一的
并且题目还让你判断了环 这不明摆着让你利用top排序进行DP吗? 这种在top序列上进行Dp的方式其实很常见
考虑建立多层图
我们对唯一存在的topp 求两个topp序列 问题可以转化为
给你两个数列 AB 问题B最多能够插入A中多少并且B序列的顺序是不变的
预处理出B数列中的每一个数所能插入的位置
定义 f[i][j] 表示前i个A前i个B 所能选的最大的个数
状态转移方程就很好写具体看代码
code:

    #include<stdio.h>
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
#define maxnn 2000
#define mm 1000010
int mapp[maxnn][maxnn];
int las[mm],en[mm],nex[mm],tot;
int rr1[mm],rr2[mm];

void add(int a,int b)
{
    en[++tot]=b;
    nex[tot]=las[a];
    las[a]=tot;
}
int las1[mm],en1[mm],nex1[mm],tot1;
void add1(int a,int b)
{
    en1[++tot1]=b;
    nex1[tot1]=las1[a];
    las1[a]=tot1;
}

int n,m;
int ru[maxnn];
int is[maxnn];
int rk1[maxnn],rk2[maxnn],cnt1,cnt2;
int maxx[maxnn],minn[maxnn];
void toppsort()
{
    queue<int> Q;
    int num=0;
    for(int i=1;i<=n;i++)
    {
        if(is[i]&&(!ru[i]))
        {
            rk1[++cnt1]=i;
            rr1[i]=cnt1;
            Q.push(i);
            num++;
        }
    }
    while(Q.size())
    {
        int r=Q.front();Q.pop();
        for(int i=las[r];i;i=nex[i])
        {
            int u=en[i];
            if(!is[u]) continue;
            ru[u]--;
            if((!ru[u])&&(is[u]))
            {
                num++;
                rk1[++cnt1]=u;rr1[u]=cnt1;
                Q.push(u);
            }
        }
    }
    if(num<m) {puts("NO"); exit(0);}
    num=0;
    for(int i=1;i<=n;i++)
    {
        if((!is[i])&&(!ru[i]))
        {
            Q.push(i);
            rk2[++cnt2]=i;
            rr2[i]=cnt2;
            num++;
        }
    }
    while(Q.size())
    {
        int r=Q.front(); Q.pop();
        for(int i=las[r];i;i=nex[i])
        {
            int u=en[i];
            if(is[u]) continue;
            ru[u]--;
            if((!ru[u])&&(!is[u]))
            {
                rk2[++cnt2]=u;
                rr2[u]=cnt2;
                Q.push(u);
                num++;
            }
        }
    }
    if(num<n-m)
    {
        puts("NO"); exit(0);
    }
}
int f[maxnn][maxnn];
int main()
{

    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&mapp[i][j]);
            if(mapp[i][j]==1)
            {
                add(j,i);
                add1(i,j);
            }
        }
    }
    int x;
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&x);
        is[x]=1;
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(mapp[i][j]&&is[i]&&is[j])ru[i]++;
            if(mapp[i][j]&&(!is[i])&&(!is[j])) ru[i]++;
        }
    toppsort();
    for(int i=1;i<=n;i++)
    {
        minn[i]=100000;
    }
    for(int i=1;i<=n;i++)
    {
        if(is[i])
            for(int j=las1[i];j;j=nex1[j])
            {
                int u=en1[j];
                if(!is[u])
                {
                    if(minn[u]==0) minn[rr2[u]]=rr1[i];
                    else minn[rr2[u]]=min(minn[rr2[u]],rr1[i]);
                }
            }
        else
        {
            for(int j=las1[i];j;j=nex1[j])
            {
                int u=en1[j];
                if(is[u])
                maxx[rr2[i]]=max(maxx[rr2[i]],rr1[u]);
            }
            

        }
    }
    int ans=0;
    for(int i=0;i<=cnt1+1;i++)
    for(int j=0;j<=cnt2;j++)
    {
      
       if(i>=1) f[i][j]=max(f[i-1][j],f[i][j]);
        if(j>=1) f[i][j]=max(f[i][j-1],f[i][j]);
        if((i>maxx[j])&&(i<=minn[j]))
        {
       
            if(j>=1)f[i][j]=max(f[i][j],f[i][j-1]+1);
        }
        ans=max(ans,f[i][j]);
    }
    printf("YES ");
    cout<<ans;
}
原文地址:https://www.cnblogs.com/OIEREDSION/p/11827997.html