Median 题解(floyd传递闭包)

题目链接

题目思路

这个题目就是等价于正着建一次边,反着建一次边,然后看第\(i\)个点在这两种情况中能到达的点都小于\(\frac{n}{2}\)

则为\(1\),否则则为\(1\)

拓扑排序上\(dp\)是对于链的一些情况来考虑

这里需要floyd传递闭包来写这个

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=1e2+5,inf=0x3f3f3f3f;
const double eps=1e-6;
int n,m;
int u[maxn*maxn],v[maxn*maxn];
int sz[maxn][2];
bitset<maxn> b[maxn];
void cal(int id){
    for(int mid=1;mid<=n;mid++){
        for(int beg=1;beg<=n;beg++){
            if(b[beg][mid]){
                b[beg]|=b[mid];
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            sz[i][id]+=b[i][j];
        }
    }
}
signed main(){
    int _;scanf("%d",&_);
    while(_--){
        memset(sz,0,sizeof(sz));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            b[i].reset();
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d",&u[i],&v[i]);
            b[u[i]][v[i]]=1;
        }
        cal(0);
        bool flag=1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(b[i][j]&&b[j][i]) flag=0;
            }
        }
        if(!flag){
            for(int i=1;i<=n;i++){
                printf("0");
            }
            printf("\n");
            continue;
        }
        for(int i=1;i<=n;i++){
            b[i].reset();
        }
        for(int i=1;i<=m;i++){
            b[v[i]][u[i]]=1;
        }
        cal(1);
        for(int i=1;i<=n;i++){
            printf("%d",max(sz[i][0],sz[i][1])<=n/2);
        }
        printf("\n");
    }
    return 0;
}

posted @ 2021-12-01 23:21  hunxuewangzi  阅读(35)  评论(0编辑  收藏  举报