Codeforces1498 E. Two Houses

题目链接
思路
因为这是一张竞赛图,由题目中也可知任意一对点之间有一条有向边。
结论:入度少的点一定能走向入度多的点。
证明:对图上的强连通分量缩点,变成一个有向拓扑图。
考虑两个强连通分量A,B。假设是由A指向B,A中的一个点为a,B中的一个点为b。a的最大入度即为\(A.size()-1\),最小入度也是\(A.size()/2\),考虑b的入度,因为A指向B,那么A中所有点和b的边都是从A指向b,所以b的入度大于等于\(A.size()\)。
因此就发现是入度少的点一定能走到入度多的点。
那就只要把这些点按度数差排序查询一下即可。
代码

#include<bits/stdc++.h>
using namespace std;

typedef pair<int, int> PII;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int N = 500 + 10, M = 2e4 + 10;
int k[N];
struct Node {
    int x, y, val;
    friend bool operator < (const Node &a, const Node &b) {
        return a.val > b.val;
    }
}a[N * N];

void solve() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &k[i]);
    }
    int idx = 0;
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= n; j++) {
            if(i == j) continue;
            if(k[i] >= k[j]) {
                a[++idx] = {i, j, k[i] - k[j]};
            }
        }
    }
    sort(a + 1, a + 1 + idx);
    for(int i = 1; i <= idx; i++) {
        printf("? %d %d\n", a[i].x, a[i].y);
        fflush(stdout);
        char s[5];
        scanf("%s", s + 1);
        if(s[1] == 'Y') {
            printf("! %d %d\n", a[i].x, a[i].y);
            return;
        }
    }
    puts("! 0 0");
}

int main() {
    // freopen("in.txt", "r", stdin);
    // int t; cin >> t; while(t--)
    solve();
    return 0;
}
上一篇:CF56E Domino Principle(BIT+dp)


下一篇:1473. 粉刷房子 III(三维动态规划)