“科大讯飞杯”第18届上海大学程序设计联赛春季赛暨高校网络友谊赛

A. 组队比赛

签到。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/4/18 12:00:50
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

int a[4];

void run() {
    for(int i = 0; i < 4; i++) cin >> a[i];
    int ans = min(abs(a[0] + a[3] - a[1] - a[2]), abs(a[0] + a[1] - a[2] - a[3]));
    ans = min(ans, abs(a[0] + a[2] - a[1] - a[3]));
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

B. 每日一报

签到。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/4/18 12:10:50
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

struct p {
    string day, num;
    double t;   
    bool operator < (const p &A) const {
        if(day != A.day) return day > A.day;
        if(t != A.t) return t > A.t;
        return num < A.num;   
    }
}a[N];

void run() {
    int n; cin >> n;
    for(int i = 1; i <= n; i++) {
        cin >> a[i].day >> a[i].num >> a[i].t;
    }   
    sort(a + 1, a + n + 1);
    vector <p> ans;
    for(int i = 1; i <= n; i++) if(a[i].t >= 38.0) {
        ans.push_back(a[i]);   
    }
    cout << sz(ans) << '\n';
    for(auto it : ans) {
        cout << it.day << ' ' << it.num << ' ' << it.t << '\n';   
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(1);
    run();
    return 0;
}

C. 最长非公共子序列

贪心。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/4/18 12:07:36
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

void run() {
    string s, t; cin >> s >> t;
    if(s == t) {
        cout << -1 << '\n';   
        return;
    }
    int n = s.length(), m = t.length();
    cout << max(n, m) << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

D. 最大字符集

00
010
0110
...
这样构造即可。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/4/18 12:42:40
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

void run() {
    int n; cin >> n;
    vector <string> ans;
    string now = "";
    for(int i = 1; i <= n; i++) now += "1";
    int fir = 0, last = now.length() - 1;
    for(int i = n, op = (n & 1 ? 0 : 1); i >= 1; i--, op ^= 1) {
        ans.push_back(now);
        int f = 0;
        now.pop_back(), --last;
        if(op) {
            if(last < fir) f = 1;
            else now[last] = '0';
        } else {
            if(fir > last) f = 1;
            else now[fir++] = '0';
        }
        if(f) break;
    }
    cout << sz(ans) << '\n';
    reverse(all(ans));
    for(auto it : ans) cout << it << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

E. 美味的序列

签到。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/4/18 12:04:51
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

void run() {
    int n; cin >> n;
    vector <int> a(n);
    for (int i = 0; i < n; i++) cin >> a[i];
    int d = 0;
    ll ans = 0;
    for(int i = 0; i < n; i++) {
        ans += a[i] - d;
        ++d;
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

F. 日期小助手

枚举。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/4/18 14:38:04
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
const int date[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int calc(int y, int m, int d)
{
    if(m==1||m==2) 
    {
        m+=12;
        y--;
    }
    int Week=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7;
    return Week + 1; 
}
    
void run() {
    int y, m, d; cin >> y >> m >> d;
    int w = calc(y, m, d);
    int cnt1 = 0, cnt2 = 0;
    if(m == 5) {
        int now = calc(y, m, 1);
        for(int i = 1; i <= d; i++) {
            if(now == 7) ++cnt1;
            now = (now % 7) + 1;
        }
    }
    if(m == 6) {
        int now = calc(y, m, 1);
        for(int i = 1; i <= d; i++) {
            if(now == 7) ++cnt2;
            now = (now % 7) + 1;
        }   
    }
    while(1) {
        w = w % 7 + 1;
        if(++d > date[m] + ((m == 2) && ((y % 400 == 0) || (y % 100 != 0 && y % 4 == 0)))) d = 1, ++m;
        if(m > 12) m = 1, ++y;
        if(m == 5 && w == 7 && ++cnt1 == 2) {
            cout << "Mother's Day: May " << d;
            if(d == 1 || d == 21 || d == 31) cout << "st, ";
            else if(d == 2 || d == 22 || d == 32) cout << "nd, ";
            else if(d == 3 || d == 23 || d == 33) cout << "rd, ";
            else cout << "th, ";
            cout << y << '\n';
            return;
        }
        if(m == 6 && w == 7 && ++cnt2 == 3) {
            cout << "Father's Day: June " << d;
            if(d == 1 || d == 21 || d == 31) cout << "st, ";
            else if(d == 2 || d == 22 || d == 32) cout << "nd, ";
            else if(d == 3 || d == 23 || d == 33) cout << "rd, ";
            else cout << "th, ";
            cout << y << '\n';
            return;               
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T;
    while(T--) run();
    return 0;
}

G. 血压游戏

题意:
给出一颗树,每个结点上有\(a_i\)只松鼠。
若一个结点上有多余\(1\)只松鼠,它们会打架,那么就会阵亡一只,每个结点在同一时刻进行该操作。
然后所有松鼠会往上跳一个结点,继续进行打架操作。
若有松鼠位于根的位置,那么往上面跳就会到安全地带,它们再也不用打架了。
计算最终多少松鼠回到地面。

思路:
注意到所有会打架的松鼠一开始都位于相同的深度,那么根据这一点我们将所有深度相同的松鼠单独拿出来计算。
显然对于一层的松鼠往上跳的过程我们可以直接自下往上\(dp\)计算。
但直接这样算复杂度是\(O(n^2)\)的,显然时空不能承受。
其实我们每一层计算的时候,有很多没有用的点,那些点我们完全没有必要在\(dp\)时加进来。我们只需要若干个有用的点就行。这就涉及到“虚树”。我们对每一层的结点拿出来构造虚树,假设一层结点为\(k\)个,那么虚树结点不超过\(2k\)个。然后直接跑\(dp\)
这样时间复杂度即为\(O(nlogn)\),瓶颈在于求\(lca\)
代码如下:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/4/19 17:26:40
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A>
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2e5 + 5;
 
int in[N], out[N], T;
int f[N][20], deep[N];
vector <int> G[N];
void dfs(int u, int fa) {
    in[u] = ++T;
    deep[u] = deep[fa] + 1;
    f[u][0] = fa;
    for(int i = 1; i < 20; i++) {
        f[u][i] = f[f[u][i - 1]][i - 1];
    }   
    for(auto v : G[u]) if(v != fa) {
        dfs(v, u);
    }
    out[u] = T;
}
int LCA(int x, int y) {
    if(deep[x] < deep[y]) swap(x, y);
    for(int i = 19; i >= 0; i--) {
        if(deep[f[x][i]] >= deep[y]) x = f[x][i];
    }  
    if(x == y) return x;
    for(int i = 19; i >= 0; i--) {
        if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];  
    }
    return f[x][0];
}
int dis(int x, int y) {
    int z = LCA(x, y);
    return deep[x] + deep[y] - 2 * deep[z];  
}
 
int V[N << 1], tot;
vector <int> vt[N];
void clear() {
    for(int i = 1; i <= tot; i++) vt[V[i]].clear();  
}
int buildVT(vector<int>& nodes) {
    static int st[N], top;
    auto cmp = [&](int x, int y) {
        return in[x] < in[y];
    };
    auto chk = [&](int x, int y) {
        return in[y] >= in[x] && in[y] <= out[x];
    };
     
    tot = 0;
    for(auto it : nodes) V[++tot] = it;
    sort(V + 1, V + 1 + tot, cmp);
    for(int i = 1, tmp = tot; i < tmp; i++) V[++tot] = LCA(V[i], V[i + 1]);
    sort(V + 1, V + 1 + tot, cmp);
    tot = unique(V + 1, V + 1 + tot) - V - 1;
 
    st[top = 1] = V[1];
    for(int i = 2; i <= tot; i++) {
        while(top > 1 && !chk(st[top], V[i])) --top;
        vt[st[top]].push_back(V[i]);  
        st[++top] = V[i];
    }
    return V[1];
}
 
int n, s;
int a[N];
vector <int> D[N];
ll dp[N];
void DP(int u) {
    if(!sz(vt[u])) dp[u] = a[u];
    else dp[u] = 0;
    for(auto v : vt[u]) {
        DP(v);
        if(dp[v]) dp[u] += max(1ll, dp[v] - (deep[v] - deep[u]));
    }  
}
 
void run() {
    cin >> n >> s;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i < n; i++) {
        int u, v; cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(s, 0);
    for(int i = 1; i <= n; i++) {
        D[deep[i]].push_back(i);  
    }
    ll ans = 0;
    for(int i = 1; i <= n; i++) if(sz(D[i])) {
        int rt = buildVT(D[i]);
        DP(rt);
        if(dp[rt]) ans += max(1ll, dp[rt] - (deep[rt] - deep[s]) - 1);
        clear();
    }
    cout << ans << '\n';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

H. 纸牌游戏

题意:
现有\(n\)张数字牌,每张都包含\(0\)~\(9\)其中一个阿拉伯数字。
现在要从中选出\(k\)张,组成一个能被\(3\)整除的非负整数,并要求组成的数最大。

思路:
容易证明,我们将所有的数按照模\(3\)进行分类,然后要选出若干个数,每类数最多选\(2\)张即可构成所有情况。
那么直接暴力就行。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/4/18 19:51:22
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;

char s[N];
int cnt[10], ans[10];

bool dfs(int x, int k, int m) {
    if(x == -1) {
        return k == 0 && m == 0;
    }
    int r = min(k, cnt[x]);
    if(x == 0) {
        int f = 1;
        for(int i = 1; i < 10; i++) {
            if(ans[i] > 0) f = 0;
        }   
        if(f) r = min(cnt[x], 1);
    }
    int l = max(0, r - 2);
    for(int i = r; i >= l; i--) {
        ans[x] = i;
        if(dfs(x - 1, k - i, (m + i * x) % 3)) return true;
    }
    return false;
}

void run() {
    int n, k;
    cin >> (s + 1) >> k;
    n = strlen(s + 1);
    for(int i = 0; i < 10; i++) cnt[i] = ans[i] = 0;
    for(int i = 1; i <= n; i++) {
        ++cnt[s[i] - '0'];
    }
    if(!dfs(9, k, 0)) cout << -1 << '\n';
    else {
        for(int i = 9; i >= 0; i--) {
            for(int j = 1; j <= ans[i]; j++) cout << i;
        }   
        cout << '\n';
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    int T; cin >> T;
    while(T--) run();
    return 0;
}

I. 古老的打字机

题意:
现有一个打字机,每次会随机打一个英文字母或者一个退格键。
现在随机敲打\(m,m\leq 1000\)次,会得到字符串\(t\)
给定\(n,n\leq 1000\)个字符串,每个字符串价值为\(v_i\)
定义最后串\(t\)的价值为每个字符串出现的次数乘以对应价值。
求得到字符串价值的期望。

思路:
根据期望线性性质,我们可以直接对每个串进行考虑,现在问题就转化为只有一个字符串时的期望价值。
我们还可以继续将问题细分,求出最终串长度为\(s\)的期望,那么我们可以用\(dp\)求出\(dp[m][s]\)
再次利用期望线性性,求出串以每个位置为开头的期望,因为题目最后要乘以\(27^m\),所以我们相当于算分子部分,即每个串出现的次数。
出现的次数即为\(所有可能的位置\cdot 在该位置出现的概率\)
那么就没了。
细节见代码:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/4/19 9:23:38
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e3 + 5, MOD = 1e9 + 7;
int qpow(ll a, ll b) {
    ll res = 1;
    while(b) {
        if(b & 1) res = res * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return res;
}
void add(int &x, int y) {
    x += y;
    if(x >= MOD) x -= MOD;
}

int dp[N][N], ipow[N];
string str[N];
int a[N];

void run() {
    int n, m; cin >> n >> m;
    ipow[0] = 1, ipow[1] = qpow(26, MOD - 2);
    for(int i = 1; i <= m; i++) ipow[i] = 1ll * ipow[i - 1] * ipow[1] % MOD;
    dp[0][0] = 1;
    for(int i = 0; i < m; i++) {
        for(int j = 0; j < N; j++) if(dp[i][j]) {
            add(dp[i + 1][max(j - 1, 0)], dp[i][j]);
            add(dp[i + 1][j + 1], 1ll * dp[i][j] * 26 % MOD);
        }
    }
    int ans = 0;
    for(int i = 1; i <= n; i++) cin >> str[i] >> a[i];
    for(int i = 1; i <= m; i++) {
        int s = 0;
        for(int j = 1; j <= n; j++) {
            int len = str[j].length();
            if(i >= len) {
                add(s, 1ll * (i - len + 1) * a[j] % MOD * ipow[len] % MOD);
            }
        }
        add(ans, 1ll * s * dp[m][i] % MOD);
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

L. 动物森友会

二分天数,然后网络流进行check即可。
只需要判断最大流是否大于\(\sum c_i\)

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/4/18 15:28:41
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A>
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2000 + 5, M = 10000 + 5;
 
int n, e;
int c[N];
vector <vector<int>> a(8);
 
template <class T>
struct Dinic{
    struct Edge{
        int v, next;
        T flow;
        Edge(){}
        Edge(int v, int next, T flow) : v(v), next(next), flow(flow) {}
    }e[M << 1];
    int head[N], tot;
    int dep[N];
    void init() {
        memset(head, -1, sizeof(head)); tot = 0;
    }
    void adde(int u, int v, T w, T rw = 0) {
        e[tot] = Edge(v, head[u], w);
        head[u] = tot++;
        e[tot] = Edge(u, head[v], rw);
        head[v] = tot++;
    }
    bool BFS(int _S, int _T) {
        memset(dep, 0, sizeof(dep));
        queue <int> q; q.push(_S); dep[_S] = 1;
        while(!q.empty()) {
            int u = q.front(); q.pop();
            for(int i = head[u]; ~i; i = e[i].next) {
                int v = e[i].v;
                if(!dep[v] && e[i].flow > 0) {
                    dep[v] = dep[u] + 1;
                    q.push(v);
                }
            }
        }
        return dep[_T] != 0;
    }
    T dfs(int _S, int _T, T a) {
        T flow = 0, f;
        if(_S == _T || a == 0) return a;
        for(int i = head[_S]; ~i; i = e[i].next) {
            int v = e[i].v;
            if(dep[v] != dep[_S] + 1) continue;
            f = dfs(v, _T, min(a, e[i].flow));
            if(f) {
                e[i].flow -= f;
                e[i ^ 1].flow += f;
                flow += f;
                a -= f;
                if(a == 0) break;
            }
        }
        if(!flow) dep[_S] = -1;
        return flow;
    }
    T dinic(int _S, int _T) {
        T max_flow = 0;
        while(BFS(_S, _T)) max_flow += dfs(_S, _T, INF);
        return max_flow;
    }
};
 
Dinic <int> solver;
 
bool chk(int x) {
    solver.init();  
    for(int i = 1; i <= 7; i++) {
        int t = (x - 1) / 7, r = (x - 1) % 7 + 1;
        ll now = 1ll * (t + (i <= r)) * e;
        if(now > (ll)INF) now = INF;
        solver.adde(0, i, now);
    }
    for(int i = 1; i <= 7; i++) {
        for(auto j : a[i]) {
            solver.adde(i, j + 7, INF);
        }
    }
    int T = 2000, sum = 0;
    for(int i = 1; i <= n; i++) {
        solver.adde(i + 7, T, c[i]);
        sum += c[i];
    }
    return solver.dinic(0, T) >= sum;
}
 
void run() {
    cin >> n >> e;
    for(int i = 1; i <= n; i++) {
        cin >> c[i]; int x; cin >> x;
        for(int j = 1; j <= x; j++) {
            int t; cin >> t;
            a[t].push_back(i);
        }  
    }
    int l = 1, r = INF, mid;
    while(l < r) {
        mid = (l + r) >> 1;
        if(chk(mid)) r = mid;
        else l = mid + 1;
    }
    cout << l << '\n';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}
posted @ 2020-04-21 08:51  heyuhhh  阅读(365)  评论(0编辑  收藏  举报