C. Peaceful Rooks

C. Peaceful Rooks_第1张图片

思路:如果是本来就位于对角线上的点,那么自然就没有必要进行移动了,否则就是在浪费操作次数。
那么不在对角线上的点一定需要操作一次,竖直移动或者水平移动到对角线上。
但是我们还发现可能会有n个点构成一个环,就像样例3一样。这个时候我们可以先把其中一个点移到空的行或列上,然后剩下的n-1个点移到对角线上,然后再把原来一出去的那个点移回到对角线上。所以当n个点够成一个环时,他们的贡献是n+1。到这里这个题目就转化成了一个图论问题。C. Peaceful Rooks_第2张图片像这样就是成环,不能直接到达(x,x)

代码:

#include
#define INF 0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef pair P;
typedef long long ll;
const int N = 2e6 + 9;
const ll MOD = 1e9 + 7;

int par[N];

int find(int x)
{
    if(x == par[x])
        return x;
    return par[x] = find(par[x]);
}

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        int n, m;
        int cnt = 0;
        cin >> n >> m;
        for(int i = 0; i < n + 1; i++)
            par[i] = i;
        for(int i = 0, x, y; i < m; i++)
        {
            cin >> x >> y;
            if(x == y)
                continue;
            if(find(x) != find(y))
            {
                par[find(x)] = find(y);
            }
            else
            {
                cnt++;
            }
            cnt++;
        }
        cout << cnt << endl;
    }
    return 0;
}

你可能感兴趣的:(c语言,c++,算法)