1. 程式人生 > >[hdu5503]EarthCup[霍爾定理]

[hdu5503]EarthCup[霍爾定理]

題意

一共 \(n\) 只球隊,兩兩之間會進行一場比賽,贏得一分輸不得分,給出每隻球隊最後的得分,問能否構造每場比賽的輸贏情況使得得分成立。多組資料

\(T\le 10,n\le 5\times 10^4\)

分析

  • 容易想到一個網路流的模型:把每場比賽看成點,連向對應的兩隻隊伍。實際上可以把每隻隊伍的拆成 \(a_i\) 個點就是二分圖的模型了。
  • 考慮霍爾定理,隊伍和隊伍之間的區別只在於 \(a\) ,所以考慮列舉隊伍數量 \(k\) ,判斷最極端的 \(k\) 只隊伍即可。\(a\) 最小的 \(k\) 只隊伍應滿足: \(\frac{k(k-1)}{2}\le \sum\limits_{i=1}^ka_i\)
    ,所以排個序判斷一下就好了。
  • 總時間複雜度 \(O(nlogn)\)

程式碼

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define go(u) for(int i = head[u], v = e[i].to; i; i=e[i].lst, v=e[i].to)
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define pb push_back
#define re(x) memset(x, 0, sizeof x)
inline int gi() {
    int x = 0,f = 1;
    char ch = getchar();
    while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar();}
    while(isdigit(ch)) { x = (x << 3) + (x << 1) + ch - 48; ch = getchar();}
    return x * f;
}
template <typename T> inline void Max(T &a, T b){if(a < b) a = b;}
template <typename T> inline void Min(T &a, T b){if(a > b) a = b;}
const int N = 5e4 + 7;
int n, T;
int a[N];
int main() {
    T = gi();
    while(T--) {
        n = gi();bool fg = 1;LL tot = 0;
        rep(i, 1, n) a[i] = gi(), tot += a[i];
        if(tot != 1ll * n * (n - 1) / 2) { 
            puts("The data have been tampered with!");
            continue;
        }
        sort(a + 1, a + 1 + n);
        LL sum = 0;
        rep(i, 1, n) {
            sum += a[i];
            if(1ll * i * (i - 1) / 2 > sum) { fg = 0; break;}
        }
        if(!fg) puts("The data have been tampered with!");
        else puts("It seems to have no problem.");
    }
    return 0;
}