1.题目链接。题目大意:有n个数,给出m个他们之间相对的大小关系,问从这m个关系中,对于每一个数,是不是可以让这个数作为这个数列的中位数。
2.传递闭包加了一点点的改进。对整个图求完传递闭包之后,对于每个点记录一下有多少个比他的的,有多少个比它小的,然后如果这两个数据有任何一个是大于n/2的,那么显然是不成立的。否则是可能的。当然,特判一下不合法,在这个有向图里面不合法的地方就是有两个点存在双向边,说明存在a>b&&b>a.这显然是不存在的。如果存在这样的数据,说明整个序列不合法,全输出0.
using namespace std;
const int maxn = 110;
int mp[maxn][maxn];
int in[maxn], out[maxn];
int n, m;
void Floyd()
{
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
mp[i][j] = mp[i][j] || (mp[i][k] && mp[k][j]);
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
memset(mp, 0, sizeof(mp));
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
for (int i = 1; i <= m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
mp[u][v] = 1;
}
Floyd();
bool flag1 = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (mp[i][j] && mp[j][i])
{
flag1 = 1;
break;
}
}
}
if (flag1)
{
for (int i = 1; i <= n; i++)
printf("0");
puts("");
continue;
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (i != j&&mp[i][j])//mp[i][j]表示i比j大,那么比j大的加一,比i小的减一
{
in[j]++;
out[i]++;
}
}
}
int mmax = n / 2;
for (int i = 1; i <= n; i++)
{
if (in[i] > mmax || out[i] > mmax)
{
printf("0");
}
else
{
printf("1");
}
}
puts("");
}
}