Problem Description
Mr. Chopsticks keeps N monsters, numbered from 1 to N. In order to train them, he holds N * (N - 1) / 2 competitions and asks the monsters to fight with each other. Any two monsters fight in exactly one competition, in which one of them beat the other. If monster A beats monster B, we say A is stronger than B. Note that the “stronger than” relation is not transitive. For example, it is possible that A beats B, B beats C but C beats A.
After finishing all the competitions, Mr. Chopsticks divides all the monsters into two teams T1 and T2, containing M and N – M monsters respectively, where each monster is in exactly one team. Mr. Chopsticks considers a team of monsters powerful if there is a way to arrange them in a queue (A1, A2, …, Am) such that monster Ai is stronger than monster Aj for any 1<=i<j<=m. Now Mr. Chopsticks wants to check whether T1 and T2 are both powerful, and if so, he wants to select k monsters from T2 to join T1 such that the selected monsters together with all the monsters in T1 can still form a powerful team and k is as large as possible. Could you help him?
After finishing all the competitions, Mr. Chopsticks divides all the monsters into two teams T1 and T2, containing M and N – M monsters respectively, where each monster is in exactly one team. Mr. Chopsticks considers a team of monsters powerful if there is a way to arrange them in a queue (A1, A2, …, Am) such that monster Ai is stronger than monster Aj for any 1<=i<j<=m. Now Mr. Chopsticks wants to check whether T1 and T2 are both powerful, and if so, he wants to select k monsters from T2 to join T1 such that the selected monsters together with all the monsters in T1 can still form a powerful team and k is as large as possible. Could you help him?
Input
The input contains multiple test cases. Each case begins with two integers N and M (2 <= N <= 1000, 1 <= M < N), indicating the number of monsters Mr. Chopsticks keeps and the number of monsters in T1 respectively. The following N lines, each contain N integers, where the jth integer in the ith line is 1 if the ith monster beats the jth monster; otherwise, it is 0. It is guaranteed that the ith integer in the jth line is 0 iff the jth integer in the ith line is 1. The ith integer in the ith line is always 0. The last line of each case contains M distinct integers, each between 1 and N inclusively, representing the monsters in T1. The input is terminated by N = M = 0.
Output
For each case, if both T1 and T2 are powerful, output “YES” and the maximum k; otherwise, output “NO”.
Sample Input
3 2 0 1 1 0 0 1 0 0 0 3 1 4 3 0 1 0 1 0 0 1 1 1 0 0 1 0 0 0 0 1 2 3 4 2 0 1 0 1 0 0 1 1 1 0 0 1 0 0 0 0 1 2 0 0
Sample Output
YES 1 NO YES 1HintIn the third example, Mr. Chopsticks can let the monster numbered 4 from T2 join into T1 to form a queue (1, 2, 4).
首先我们暴力判断T1和T2是否都满足
判断方法是对于每个点i,判断能到达多少个点
然后看这些数量是否为1到m或n-m的排列
然后考虑问题2
因为T2满足。所以我们按照T2顺序插入可以不用考虑T2之间互相影响
对于每个T2,找到可以插入的T1的位置,不能插入则直接删除这个点
因为T2满足题意,所以T2是个DAG,因此我们拓扑排序,每个点有个权值表示可以插入的T1的位置
找权值单调不下降的最长链的长度即为答案
这题一开始T了我以为是常数写大了。。结果是scanf的耗时太多了。加了个读入优化就卡过去了
#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
inline long long read()
{
long long x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int mx[1001][1001];
bool v[1001];
int vx[1001];
int a[1001],b[1001],c[1001],f[1001];
struct line
{
int s,t;
int next;
}aa[1000001];
int head[1001];
int edge;
inline void add(int s,int t)
{
aa[edge].next=head[s];
head[s]=edge;
aa[edge].s=s;
aa[edge].t=t;
}
int deg[1001];
queue<int> Q;
int main()
{
// freopen("1003.in","r",stdin);
// freopen("1003.ans","w",stdout);
int n,m;
n=read();
m=read();
// scanf("%d%d",&n,&m);
while(n!=0&&m!=0)
{
int i,j,k;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
mx[i][j]=read();
// scanf("%d",&mx[i][j]);
memset(v,false,sizeof(v));
for(i=1;i<=m;i++)
{
a[i]=read();
// scanf("%d",&a[i]);
v[a[i]]=true;
}
int p=0;
for(j=1;j<=n;j++)
{
if(!v[j])
{
p++;
b[p]=j;
}
}
bool flag=true;
memset(vx,0,sizeof(vx));
for(i=1;i<=n-m;i++)
{
int sx=0;
for(j=1;j<=n-m;j++)
{
if(mx[b[i]][b[j]])
sx++;
}
if(!vx[sx])
vx[sx]=1;
else
{
flag=false;
break;
}
}
memset(vx,0,sizeof(vx));
for(i=1;i<=m;i++)
{
int sx=0;
for(j=1;j<=m;j++)
{
if(mx[a[i]][a[j]])
sx++;
}
if(!vx[sx])
vx[sx]=a[i];
else
{
flag=false;
break;
}
}
if(flag)
{
printf("YES ");
for(i=1;i<=n-m;i++)
{
int sx=0,la=0;
bool flag=true;
for(j=0;j<m;j++)
{
if(mx[b[i]][vx[j]])
{
sx++;
la=j+1;
}
else
break;
}
for(k=j;k<m;k++)
{
if(!mx[vx[k]][b[i]])
{
flag=false;
break;
}
}
if(flag)
c[i]=n-la;
else
c[i]=2100000000;
}
// sort(c+1,c+1+n-m);
memset(f,0,sizeof(f));
memset(head,0,sizeof(head));
//memset(aa,0,sizeof(aa));
memset(deg,0,sizeof(deg));
edge=0;
int ans=0;
for(i=1;i<=n-m;i++)
{
if(c[i]==2100000000)
continue;
for(j=1;j<=n-m;j++)
{
if(c[j]!=2100000000)
{
if(mx[b[i]][b[j]])
{
edge++;
add(i,j);
deg[j]++;
}
}
}
}
memset(f,0,sizeof(f));
for(i=1;i<=n-m;i++)
{
if(c[i]==2100000000)
continue;
if(deg[i]==0)
Q.push(i);
}
while(!Q.empty())
{
int d=Q.front();
f[d]=max(f[d],1);
Q.pop();
for(i=head[d];i!=0;i=aa[i].next)
{
int t=aa[i].t;
deg[t]--;
if(c[d]<=c[t])
f[t]=max(f[t],f[d]+1);
if(deg[t]==0)
Q.push(t);
}
ans=max(ans,f[d]);
}
printf("%d\n",ans);
}
else
printf("NO\n");
n=read();
m=read();;
// scanf("%d%d",&n,&m);
}
return 0;
}