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];
}