标签:
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
YES 1
NO
YES 1
In the third example, Mr. Chopsticks can let the monster numbered 4 from T2 join into T1 to form a queue (1, 2, 4).
题目大意:
Chopsticks养了n只怪兽。他们有制约关系,用一个矩阵
要注意制约关系不具备传递性,例如可以有A能打败B B能打败C C能打败A的情况。
现在Chop挑选出m只怪兽组成T1队,剩下n-m只怪兽组成T2队
询问T1队与T2队是否合法
合法是指存在某种排列
排列中任意一只怪兽都能打败他右边所有怪兽。
然后问最多从T2中能选出几只怪兽插入到T1中,能保证T1依旧合法?
第一个判断用拓扑排序即可,什么姿势都可以。
如果是YES,可以在拓扑排序中找到两个队伍的拓扑序。在T2的拓扑序列中从低到高(最弱的怪兽到能打败T2中所有怪兽的怪兽)遍历,在T1中找到它可以放置的位置,可知这个位置是固定的!,否则就不能放入T1
然后找到最长上升/下降子序列,这个取决于很多因素,比如拓扑序存储方式,遍历方式等等
然后测试通过,兴高采烈的提交…………………………
Surprise!!TLE……
憋动手。。。并不是算法有误,改一下输入试试。。。scanf(“%d”)1000*1000本题会爆炸(其实本地测后台数据并没爆……)
改成gets,然后从字符串中得到数字即可,因为只有1和0,用下标。
神题啊…………
代码如下:
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <list>
#include <algorithm>
#include <map>
#include <set>
#define LL long long
#define Pr pair<int,int>
#define fread(ch) freopen(ch,"r",stdin)
#define fwrite(ch) freopen(ch,"w",stdout)
using namespace std;
const int INF = 0x3f3f3f3f;
const int msz = 10000;
const int mod = 1e9+7;
const double eps = 1e-8;
int mp[1111][1111];
int in[1111];
int team[1111];
int vc[2][1111];
int n,m,tp[2];
bool topo()
{
memset(in,0,sizeof(in));
int u,v;
for(int i = 1; i <= n; ++i)
{
for(int j = i+1; j <= n; ++j)
{
if(team[i] != team[j]) continue;
if(mp[i][j]) in[j]++;
if(mp[j][i]) in[i]++;
}
}
for(int i = 1; i <= n; ++i)
{
for(u = 1; u <= n; ++u)
if(!in[u]) break;
if(u == n+1) return false;
in[u]--;
vc[team[u]][tp[team[u]]++] = u;
for(v = 1; v <= n; ++v)
{
if(mp[u][v] && team[u] == team[v])
in[v]--;
}
}
return true;
}
int dp[1111];
void Search(int l,int &len,int x)
{
int r = len;
int ans = -1;
while(l <= r)
{
int mid = (l+r)>>1;
if(dp[mid] <= x) l = mid+1;
else
{
ans = mid;
r = mid-1;
}
}
if(ans == -1) ans = len++;
dp[ans] = x;
}
int solve()
{
int len = 0;
memset(dp,0,sizeof(dp));
int u,v;
for(int i = 0; i < tp[0]; ++i)
{
int pos = 1;
u = vc[0][i];
//printf("%d:\n",u);
for(int j = tp[1]-1; j >= 0; --j)
{
v = vc[1][j];
//printf("%d->%d %d\n",v,u,mp[v][u]);
if(mp[v][u])
{
if(pos <= 1) pos = j+2;
}
else if(pos != 1)
{
pos = -1;
break;
}
}
//printf("%d\n---------\n",pos);
if(pos == -1) continue;
Search(0,len,pos);
}
return len;
}
//#include <ctime>
char str[2333];
int main()
{
//double x = clock();
//fread("1003.in");
//fwrite("test.out");
while(~scanf("%d%d\n",&n,&m) && (n+m))
{
tp[0] = tp[1] = 0;
for(int i = 1; i <= n; ++i)
{
gets(str);
for(int j = 1; j <= n; ++j)
{
char ch = str[j*2-2];
mp[i][j] = ch-‘0‘;
}
}
int x;
memset(team,0,sizeof(team));
for(int i = 0; i < m; ++i)
{
scanf("%d",&x);
team[x] = 1;
}
if(!topo())
{
puts("NO");
continue;
}
printf("YES %d\n",solve());
}
//printf("%f\n",(clock()-x)/CLOCKS_PER_SEC);
return 0;
}
标签:
原文地址:http://blog.csdn.net/challengerrumble/article/details/52179319