E. Cross Swapping

Codeforces Round #812 (Div. 2)

E. Cross Swapping

在这里插入图片描述

Example

input

Copy

2
3
2 1 2
2 1 2
1 1 2
4
3 3 1 2
1 1 3 1
3 2 3 2
2 3 3 1

output

Copy

2 1 1
2 1 1
2 2 2
3 1 1 2
3 1 2 1
3 3 3 3
2 3 2 1

题解:

通过观察可以发现对于g[i][j]只能和g[j][i]互相换位置。因此对于g[i][j]g[j][i]的位置进行贪心讨论。从头开始逐行扫描,如果g[i][j]<g[j][i]则需要交换,因此需要对操作i和操作j种正好一个操作一次。如果不需要换位置,那么i操作和j操作要么一个都没做,要么全都做了。

这个剩下的就是带扩展域的并查集的模板题了。

const int N=1000010,M=N*2,mod=1e9+7;
int n,m,k,a[N];
int g[1010][1010];
int fa[N],vis[N],w[N];

int find(int x){
    
    
	if(fa[x]!=x){
    
    
		int p=find(fa[x]);
		w[x] ^= w[fa[x]];
		fa[x]=p;
	}
	return fa[x];
}

void solve(){
    
    
	n=read();
	rep(i,1,n) fa[i]=i,w[i]=0;
	rep(i,1,n) rep(j,1,n) 
		g[i][j]=read();
	for(int i=1;i<=n;++i){
    
    
		for(int j=i+1;j<=n;++j){
    
    
			if(g[i][j]<g[j][i]){
    
    
				int pi=find(i),pj=find(j);
				if(pi!=pj){
    
    
					fa[pi]=pj;
					w[pi]=w[i]^w[j];
				}
			}
			else if(g[i][j]>g[j][i]){
    
    
				int pi=find(i),pj=find(j);
				if(pi!=pj){
    
    
					fa[pi]=pj;
					w[pi]=w[i]^w[j]^1;
				}
			}
		}
	}
	
	rep(i,1,n) {
    
    
		find(i);
		if(w[i])
			rep(j,1,n) swap(g[i][j], g[j][i]);
	}
	
	for(int i=1;i<=n;i++)
            for(int j=1;j <= n;j++)
                cout << g[i][j] << " \n"[j == n];
}

猜你喜欢

转载自blog.csdn.net/m0_51780913/article/details/126337173
今日推荐