CF1713E. Cross Swapping
题意
的矩阵 ,每次操作可以选择一个 ,交换每个 与 。可以进行若干次操作,求能够得到的字典序最小的矩阵(即按一行一行的顺序对元素作比较)。
思路
考虑任意一个操作做两次其效果会抵消,如果要交换 与 ,则必然是 和 中一个进行操作,另外一个不进行。如果不要交换,则要么两者都进行操作,要么都不进行。f发现所有的操作可以构成一个二分图,于是我们可以按顺序贪心地考虑,对于每个 来决定是否交换,如果 ,那么则需要交换,否则不需要,相等的时候不用考虑,交不交换都不影响。外如果操作间会发生冲突,则舍去准备加入的操作,可以用扩展域并查集来维护每个操作所属的集合,如果需要交换,则在 间连边,表示不会同时进行,否则新建节点 ,连边 和 表示需要同时进行,最后进行二分图染色,任选其中一个部分执行对应操作计科,复杂度 。
代码
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
using LL = long long;
using LD = long double;
using ULL = unsigned long long;
using PII = pair<LL, LL>;
using TP = tuple<int, int, int>;
#define all(x) x.begin(),x.end()
#define mst(x,v) memset(x,v,sizeof(x))
#define mul(x,y) (1ll*(x)*(y)%mod)
#define mk make_pair
//#define int LL
//#define double LD
#define lc tr[x].ch[0]
#define rc tr[x].ch[1]
#define endl '\n'
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#pragma warning(disable : 4996)
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
const double eps = 1e-10;
const double pi = acos(-1);
const LL MOD = 1000000007;
const LL mod = 998244353;
const int maxn = 1010;
int T, N, A[maxn][maxn], par[maxn * 2], rk[maxn * 2], col[maxn * maxn], tot;
vector<int>G[maxn * maxn];
void add_edge(int from, int to)
{
G[from].push_back(to);
G[to].push_back(from);
}
void init()
{
for (int i = 1; i <= N * 2; i++)
par[i] = i, rk[i] = 0;
}
int find(int x)
{
if (par[x] == x)
return x;
return par[x] = find(par[x]);
}
void unite(int x, int y)
{
x = find(x), y = find(y);
if (x == y)
return;
if (rk[x] < rk[y])
par[x] = y;
else
{
par[y] = x;
if (rk[x] == rk[y])
rk[x]++;
}
}
bool same(int x, int y)
{
return find(x) == find(y);
}
void dfs(int v, int p, int x)
{
col[v] = x;
for (auto& to : G[v])
{
if (to == p || col[to] != -1)
continue;
dfs(to, v, x ^ 1);
}
}
void solve()
{
init(), tot = N;
for (int i = 1; i <= N; i++)
{
for (int j = i + 1; j <= N; j++)
{
if (A[i][j] == A[j][i])
continue;
if (A[i][j] > A[j][i])
{
if (!same(i, j) && !same(i + N, j + N))
unite(i, j + N), unite(j, i + N), add_edge(i, j);
}
else
{
if (!same(i, j + N) && !same(i + N, j))
unite(i, j), unite(i + N, j + N), add_edge(i, ++tot), add_edge(tot, j);
}
}
}
for (int i = 1; i <= N; i++)
{
if (col[i] == -1)
dfs(i, 0, 1);
}
for (int k = 1; k <= N; k++)
{
if (col[k]==1)
{
for (int i = 1; i <= N; i++)
swap(A[k][i], A[i][k]);
}
}
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
cout << A[i][j] << ' ';
cout << endl;
}
for (int i = 1; i <= tot; i++)
G[i].clear(), col[i] = -1;
}
int main()
{
IOS;
mst(col, -1);
cin >> T;
while (T--)
{
cin >> N;
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
cin >> A[i][j];
}
solve();
}
return 0;
}
标签:
Codeforces
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】