标签:相等 -- pop size 具体细节 分配 oid 大小 拓扑
题意:总共有n+m个点,每一个点都有一个val,给出一个n*m的矩阵,矩阵中第i行第j列的为=,表示 i 点 和 j+n个点的值相等,<表示i 点比j+n个点的值小,> 刚好相反
要求用最少的值给每一个点确定一个val,满足如上那个矩阵,如果不存在输出Yes
存在输出每一个点的val
题解:大小关系可以转化为有向边,等于关系则是利用并查集进行缩点,因此value的分配可以利用拓扑排序来解决,如果存在环说明无解
具体细节看代码
int fa[maxn]; int Find(int x){ return fa[x]==x?x:fa[x]=Find(fa[x]); } int n,m; char sym[1005][1005]; int id[maxn]; int head[maxn],ver[maxm],nex[maxm],tot; void inline AddEdge(int x,int y){ ver[++tot]=y,nex[tot]=head[x],head[x]=tot; } int d[maxn]; bool vis[maxn]; int main(){ cin>>n>>m; for(int i=1;i<=n+m;i++) fa[i]=i; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ cin>>sym[i][j]; if(sym[i][j]==‘=‘) { int px=Find(i),py=Find(j+n); if(px!=py){ fa[px]=py; } } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(sym[i][j]==‘<‘) { AddEdge(Find(i),Find(j+n)); d[Find(j+n)]++; } else if(sym[i][j]==‘>‘){ AddEdge(Find(j+n),Find(i)); d[Find(i)]++; } } } queue<int> q; for(int i=1;i<=n+m;i++) if(!d[Find(i)]) q.push(Find(i)); while(q.size()){ int x=q.front();q.pop(); if(vis[x]) continue; vis[x]=1; for(int i=head[x];i;i=nex[i]){ int y=ver[i]; d[y]--; id[y]=max(id[y],id[x]+1); if(!d[y]) { q.push(y); } } } for(int i=1;i<=n+m;i++) if(d[Find(i)]) { cout<<"No"; return 0; } puts("Yes"); for(int i=1;i<=n;i++) cout<<id[Find(i)]+1<<‘ ‘; cout<<endl; for(int i=1;i<=m;i++) cout<<id[Find(i+n)]+1<<‘ ‘; cout<<endl; }
标签:相等 -- pop size 具体细节 分配 oid 大小 拓扑
原文地址:https://www.cnblogs.com/033000-/p/12342647.html