cf1131D

题意:总共有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;
}

  

原文地址:https://www.cnblogs.com/033000-/p/12342647.html