CF1131D Gourmet choice(并查集,拓扑排序)

这题CF给的难度是2000,但我感觉没这么高啊……

题目链接:CF原网

题目大意:有两个正整数序列 $a,b$,长度分别为 $n,m$。给出所有 $a_i$ 和 $b_j(1\le i\le n,1\le j\le m)$ 的大小关系(大于,小于或者等于),请构造出符合条件的 $a$ 和 $b$。如果无解,输出NO。如果有多个解,输出 $a,b$ 中最大元素最小的方案。

$1\le n,m\le 1000$。


这题一眼差分约束。但是看着没有具体的数字……(主要是我不会打)

然而二眼就是拓扑排序。每次将小的数往大的数连边,然后跑拓扑排序。规定一开始入度为 $0$ 的点的值为 $1$,然后拓扑时简单转移一下就好了。如果有点没有被遍历到(就是大小关系有环),那么显然无解。

不过有相同的元素……看着不好搞……

算了,直接上并查集。把相同的元素压到一个集合,然后把这些点看成一个点操作。

时间复杂度 $O(nm)$。

CF1131D Gourmet choice(并查集,拓扑排序)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=1000100;
#define MP make_pair
#define PB push_back
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
    char ch=getchar();int x=0,f=0;
    while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
int n,m,el,head[2020],to[maxn],nxt[maxn],q[2020],h=1,r,deg[2020],fa[2020],val[maxn];
char mp[1010][1010];
bool vis[2020];
inline void add(int u,int v){
    to[++el]=v;nxt[el]=head[u];head[u]=el;deg[v]++;
}
int getfa(int x){
    return x==fa[x]?x:fa[x]=getfa(fa[x]);
}
void unite(int x,int y){
    x=getfa(x);y=getfa(y);
    if(x!=y) fa[x]=y;
}
int main(){
    n=read();m=read();
    FOR(i,1,n) scanf("%s",mp[i]+1);
    FOR(i,1,n+m) fa[i]=i;
    FOR(i,1,n) FOR(j,1,m) if(mp[i][j]=='=') unite(i,j+n);
    FOR(i,1,n) FOR(j,1,m){
        if(mp[i][j]=='<') add(getfa(i),getfa(j+n));
        if(mp[i][j]=='>') add(getfa(j+n),getfa(i));
    }
    FOR(i,1,n+m) if(i==getfa(i) && !deg[i]) q[++r]=i,val[i]=1,vis[i]=true;
    while(h<=r){
        int u=q[h++];
        for(int i=head[u];i;i=nxt[i]){
            int v=to[i];
            if(vis[v]) continue;
            if(!--deg[v]){
                vis[v]=true;
                val[v]=val[u]+1;
                q[++r]=v;
            }
        }
    }
    FOR(i,1,n+m) if(i==getfa(i) && !vis[i]) return puts("No"),0;
    puts("Yes");
    FOR(i,1,n) printf("%d ",val[getfa(i)]);
    puts("");
    FOR(i,1,m) printf("%d ",val[getfa(i+n)]);
}
View Code

 

上一篇:MySQL 高可用架构 - MHA环境部署记录


下一篇:最小生成树 kruskal算法