您的位置:首页 > 其它

hdu 5811 Colosseo (拓扑排序 + 最长上升子序列)

2016-08-12 16:20 375 查看


Colosseo

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 645    Accepted Submission(s): 130


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?

 

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 1

Hint
In 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 分别做次拓扑排序 把两个序列记录下来

如果两个都不成环 就是 YES 的情况

否则就是 NO

对YES的情况 按排好的拓扑序把 T2的元素 分别判断 能否加入T1 能的话 记录位置

最后对  位置数组 求最长上升子序列 (不严格递增)

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cctype>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<bitset>
#define pi acos(-1.0)
#define inf 1<<29
#define INF 0x3fffffff
#define zero 1e-8

const int li[] = { -1, 0, 1, 0};
const int lj[] = {0, -1, 0, 1};

using namespace std;

const int N = 1000 + 107;

int t1
, t2
;
int edge

;
bool r1
, r2
, flag1
, flag2
;
int Rank
, sum1
, sum2
;
int n, t;

int que1
, que2
, head1, head2, tail1, tail2;
int id1
, id2
;

void show(int *id, int t, int flag)
{
for (int i = 0; i <= t; ++i)
cout << "id " << flag << ": " << id[i] << endl;
}

void init()
{
memset(sum1, 0, sizeof(sum1));
memset(sum2, 0, sizeof(sum2));
memset(flag1, 0, sizeof(flag1));
memset(flag2, 0, sizeof(flag2));
memset(Rank, 0, sizeof(Rank));
memset(t1, 0, sizeof(t1));
memset(t2, 0, sizeof(t2));
memset(r1, 0, sizeof(r1));
memset(r2, 0, sizeof(r2));
}
bool judge()
{

int j = 0;
tail1 = tail2 = head1 = head2 = 0;

for (int i = 1; i <= N; ++i)
if (!r1[i]) {
t2[j++] = i;
r2[i] = true;
}

for (int i = 0; i < t; ++i) {
for (int j = 1; j <= n; ++j)
if (r1[j] && j != t1[i]) {
sum1[t1[i]] += !edge[t1[i]][j];

}
if (!sum1[t1[i]]) que1[tail1++] = t1[i], flag1[t1[i]] = true;
}
for (int i = 0; i < n - t; ++i) {
for (int j = 1; j <= n; ++j)
if (r2[j] && j != t2[i]) sum2[t2[i]] += !edge[t2[i]][j];
if (!sum2[t2[i]]) que2[tail2++] = t2[i], flag2[t2[i]] = true;
}
int w = 0;

for (; head1 < tail1; head1++) {
id1[++w] = que1[head1];
for (int j = 1; j <= n; ++j)
if (r1[j] && j != que1[head1]) {
if (edge[que1[head1]][j])
sum1[j] -= 1;
if (!sum1[j] && !flag1[j]) {
que1[tail1++] = j;
flag1[j] = true;
}
}
}
if (tail1 != t) return false;
w = 0;
for (; head2 < tail2; head2++) {
id2[++w] = que2[head2];
for (int j = 1; j <= n; ++j)
if (r2[j] && j != que2[head2]) {
if (edge[que2[head2]][j])
sum2[j] -= 1;
if (!sum2[j] && !flag2[j]) {
que2[tail2++] = j;
flag2[j] = true;
}
}
}

if (tail2 != n - t) return false;
return true;
}

int sta
;
int maxup(int cnt)
{
memset(sta, 0, sizeof(sta));
int top = 0;

for (int i = 0; i < cnt; ++i) {
int maxx = 0;
for (int j = 1; j <= Rank[i]; ++j) {
maxx = maxx > sta[j] ? maxx : sta[j];
}
sta[Rank[i]] = maxx + 1;
top = top > sta[Rank[i]] ? top : sta[Rank[i]];
}

return top;
}
int DO()
{
int cnt = 0;
for (int i = 1; i <= n - t; ++i) {
int tag;
bool flag = 0, tip = 0;
for (int j = t; j > 0; --j) {
if (edge[id2[i]][id1[j]]) {
if (flag) {
tip = 1;
break;
}
tag = j - 1;
}
if (edge[id1[j]][id2[i]] && !flag) {
tag = j;
flag = true;
}
}
if (!tip) {
Rank[cnt++] = tag + 1;
}
}
return maxup(cnt);
}

int read()
{
int v = 0, f = 1;
char c = getchar();
while( c < 48 || 57 < c ) {
if(c == '-') f = -1;
c = getchar();
}
while(48 <= c && c <= 57)
v = v * 10 + c - 48, c = getchar();
return v * f;
}
char str
;

int main()
{

while(~scanf("%d %d", &n, &t)) {

if (!n && !t) break;
init();
getchar();
for (int i = 1; i <= n; ++i) {
gets(str);
int kk = 0;
for (int j = 1; j <= n; ++j, ++kk)
edge[i][j] = str[kk++] - '0';;
}
int kk = 0;
for (int i = 0; i < t; ++i) {
t1[i] = read();
r1[t1[i]] = true;
}

if (!judge()) printf("NO\n");
else printf("YES %d\n", DO());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: