首先判断一下两个集合是否能够拓扑排序,顺便记录下每个节点的拓扑序。
然后看T2中每个点在T1中能够放在哪一个位置,记录下这个位置Pi。
然后T2中(按拓扑序排好),计算Pi的一个非严格递增的LIS。LIS长度就是答案。
这题scanf读入都900+ms了,有时直接卡TLE。改用gets整行读入,时间上会有很大改进。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-8; void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } inline int read() { char c = getchar(); while(!isdigit(c)) c = getchar(); int x = 0; while(isdigit(c)) { x = x * 10 + c - ‘0‘; c = getchar(); } return x; } const int maxn=1010; int n,m,g[maxn][maxn],r[maxn],d[maxn],a[maxn],LIS[maxn],dp[maxn]; bool f[maxn]; struct Edge {int u,v,nx;}e[maxn*maxn]; int sz,h[maxn]; char s[3000]; bool Top(int x) { queue<int>Q; sz=0; memset(h,-1,sizeof h); memset(r,0,sizeof r); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(f[i]==x&&f[j]==x&&g[i][j]==1) r[j]++, e[sz].u=i, e[sz].v=j, e[sz].nx=h[i], h[i]=sz++; sz=0; for(int i=1;i<=n;i++) if(f[i]==x&&r[i]==0) Q.push(i); while(!Q.empty()) { int t=Q.front(); Q.pop(); sz++; d[t]=sz; for(int i=h[t];i!=-1;i=e[i].nx) { r[e[i].v]--; if(r[e[i].v]==0) Q.push(e[i].v); } } if(x==1) { if(sz!=m) return 0; return 1; } else { if(sz!=n-m) return 0; return 1; } } int main() { while(~scanf("%d%d",&n,&m)) { getchar(); if(n==0&&m==0) break; for(int i=1;i<=n;i++) { gets(s); int p=0; for(int j=1;j<=n;j++) { g[i][j]=s[p]-‘0‘; p=p+2; } } memset(f,0,sizeof f); for(int i=1;i<=m;i++) {int x; scanf("%d",&x),f[x]=1;} bool x1=Top(1), x2=Top(0); if(x1==0||x2==0) { printf("NO\n"); continue; } for(int i=1;i<=n;i++) { if(f[i]) continue; int L=m, R=0; for(int j=1;j<=n;j++) { if(!f[j]) continue; if(g[i][j]) L=min(L,d[j]-1); else R=max(R,d[j]); } if(L!=R) a[i]=-1; else a[i]=L; } memset(LIS,-1,sizeof LIS); for(int i=1;i<=n;i++) { if(f[i]) continue; LIS[d[i]]=a[i]; } int ans=0; memset(dp,0,sizeof dp); for(int i=1;i<=n-m;i++) { if(LIS[i]==-1) continue; int pre=0; for(int j=1;j<i;j++) if(LIS[j]<=LIS[i]) pre=max(pre,dp[j]); dp[i]=pre+1; ans=max(ans,dp[i]); } printf("YES %d\n",ans); } return 0; }
时间: 2024-10-22 02:31:14