zoukankan      html  css  js  c++  java
  • 2016 Multi-University Training Contest 1

    1001 Abandoned country

    先做最小生成树(边权不同保证唯一)。

    然后打牌一下sz,单边贡献为边权乘两头sz积。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <vector>
      5 #include <algorithm>
      6 using namespace std;
      7 typedef long long LL;
      8 const int maxn = 1e5 + 10;
      9 int n, m;
     10 LL ans;
     11 
     12 
     13 // G
     14 struct Edge
     15 {
     16     int from, to, val;
     17     Edge(int F, int T, int V): from(F), to(T), val(V){}
     18     friend bool operator < (Edge A, Edge B)
     19     {
     20         return A.val < B.val;
     21     }
     22 };
     23 vector<Edge> vec;
     24 
     25 
     26 // UF
     27 int fa[maxn];
     28 int Find(int x)
     29 {
     30     return fa[x] == x ? x : fa[x] = Find(fa[x]);
     31 }
     32 void Union(int x, int y)
     33 {
     34     x = Find(x);
     35     y = Find(y);
     36     fa[y] = x;
     37 }
     38 
     39 
     40 // tree
     41 int cnt, h[maxn];
     42 struct edge
     43 {
     44     int to, pre, val;
     45 } e[maxn<<1];
     46 void add(int from, int to, int val)
     47 {
     48     cnt++;
     49     e[cnt].pre = h[from];
     50     e[cnt].to = to;
     51     e[cnt].val = val;
     52     h[from] = cnt;
     53 }
     54 
     55 
     56 // Kruskal
     57 LL Kruskal()
     58 {
     59     LL ret = 0LL;
     60     sort(vec.begin(), vec.end());
     61     int sz = vec.size();
     62     for(int i = 0; i < sz; i++)
     63     {
     64         Edge tmp = vec[i];
     65         int a = tmp.from, b = tmp.to, v = tmp.val;
     66         if(Find(a) == Find(b)) continue;
     67         add(a, b, v), add(b, a, v);
     68         Union(a, b);
     69         ret = ret + v;
     70     }
     71     return ret;
     72 }
     73 
     74 
     75 // dp
     76 int sz[maxn];
     77 void dfs(int x, int f)
     78 {
     79     sz[x] = 1;
     80     for(int i = h[x]; i; i = e[i].pre)
     81     {
     82         int to = e[i].to, v = e[i].val;
     83         if(to == f) continue;
     84         dfs(to, x);
     85         sz[x] += sz[to];
     86         ans += (LL) v * sz[to] * (n - sz[to]);
     87     }
     88 }
     89 
     90 
     91 void init()
     92 {
     93     ans = 0LL;
     94     cnt = 0;
     95     vec.clear();
     96     memset(h, 0, sizeof(h));
     97     for(int i = 0; i < maxn; i++) fa[i] = i;
     98 }
     99 
    100 
    101 int main(void)
    102 {
    103     int T;
    104     scanf("%d", &T);
    105     while(T--)
    106     {
    107         init();
    108         scanf("%d %d", &n, &m);
    109         for(int i = 1; i <= m; i++)
    110         {
    111             int a, b, v;
    112             scanf("%d %d %d", &a, &b, &v);
    113             vec.push_back(Edge(a, b, v));
    114         }
    115         LL ans1 = Kruskal();
    116         dfs(1, 0);
    117         printf("%I64d %.2f
    ", ans1, 2.0 * ans / n / (n - 1));
    118     }
    119     return 0;
    120 }
    Aguin

    1002 Chess

    单行2^20局面暴力打好sg,每行^一下。

     1 #include <iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 int sg[1<<20];
     5 
     6 void cal(int x)
     7 {
     8     int last = -1, vis[20] = {0};
     9     for(int i = 0; i < 20; i++)
    10     {
    11         if(!(x & (1 << i))) last = i;
    12         else if(last != -1) vis[sg[((1<<last)|(1<<i))^x]] = 1;
    13     }
    14     for(int i = 0; i <= 20; i++)
    15     if(!vis[i]) {sg[x] = i; return;}
    16 }
    17 
    18 int main(void)
    19 {
    20     for(int i = 0; i < (1 << 20); i++) cal(i);
    21 
    22     int T;
    23     scanf("%d", &T);
    24     while(T--)
    25     {
    26         int N, ans = 0;
    27         scanf("%d", &N);
    28         for(int i = 1; i <= N; i++)
    29         {
    30             int m, x = 0;
    31             scanf("%d", &m);
    32             for(int i = 0; i < m; i++)
    33             {
    34                 int y;
    35                 scanf("%d", &y);
    36                 x += 1 << (20 - y);
    37             }
    38             ans ^= sg[x];
    39         }
    40         puts(ans ? "YES" : "NO");
    41     }
    42     return 0;
    43 }
    Aguin

    1003 Game

    1004 GCD

    打好st表,对每个固定的左端点,gcd最多只有logai个下降点。

    可以二分每个下降点的位置,更好的方法是从右往左枚举左端点,维护下降点序列。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <map>
     4 #include <set>
     5 using namespace std;
     6 typedef long long LL;
     7 const int maxn = 1e5 + 10;
     8 map<LL, LL> M;
     9 set<int> S;
    10 set<int> :: iterator it;
    11 int N;
    12 
    13 LL gcd(LL a, LL b)
    14 {
    15     return a % b ? gcd(b, a % b) : b;
    16 }
    17 
    18 // RMQ
    19 LL a[maxn], rmq[maxn][20];
    20 void RMQ_init()
    21 {
    22     for(int i = 1; i <= N; i++) rmq[i][0] = a[i];
    23     for(int j = 1; (1 << j) <= N; j++)
    24         for(int i = 1; i + ( 1 << j ) - 1 <= N; i++)
    25             rmq[i][j] = gcd(rmq[i][j-1] , rmq[i+(1<<j-1)][j-1]);
    26 }
    27 int RMQ_query(int l, int r)
    28 {
    29     int k = 0;
    30     while( ( 1 << (k + 1) ) <= r - l + 1 ) k++;
    31     return gcd(rmq[l][k], rmq[r-(1<<k)+1][k]);
    32 }
    33 
    34 int main(void)
    35 {
    36     int T;
    37     scanf("%d", &T);
    38     for(int kase = 1; kase <= T; kase++)
    39     {
    40         scanf("%d", &N);
    41         for(int i = 1; i <= N; i++) scanf("%I64d", a + i);
    42         RMQ_init();
    43 
    44         S.clear(), M.clear();
    45         for(int l = N; l; l--)
    46         {
    47             int last = N;
    48             LL now = RMQ_query(l, N);
    49             for(it = S.begin(); it != S.end();)
    50             {
    51                 LL tmp = RMQ_query(l, -(*it));
    52                 if(tmp == now) S.erase(it++);
    53                 else
    54                 {
    55                     M[now] += (LL) (last + *it);
    56                     now = tmp;
    57                     last = -(*(it++));
    58                 }
    59             }
    60             M[now] += (LL) (last - l);
    61             M[a[l]]++;
    62             if(a[l] != now) S.insert(-l);
    63         }
    64 
    65         int Q;
    66         scanf("%d", &Q);
    67         printf("Case #%d:
    ", kase);
    68         for(int i = 0; i < Q; i++)
    69         {
    70             int l, r;
    71             scanf("%d %d", &l, &r);
    72             LL ans = RMQ_query(l, r);
    73             printf("%I64d %I64d
    ", ans, M[ans]);
    74         }
    75 
    76     }
    77     return 0;
    78 }
    Aguin

    1005 Necklace

    枚举yin排列,以yang和空位建二分图。

    空位两边yin不会使yang褪色则连边,N - 最大匹配即为答案。

    习惯用Dinic跑,结果1s+。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <queue>
      6 using namespace std;
      7 const int INF = 1e9;
      8 int lv[22], it[22];
      9 int cnt, h[22];
     10 
     11 struct edge
     12 {
     13     int to, pre, cap;
     14 } e[1111];
     15 
     16 void init()
     17 {
     18     memset(h, -1, sizeof(h));
     19     cnt = 0;
     20 }
     21 
     22 void add(int from, int to, int cap)
     23 {
     24     e[cnt].pre = h[from];
     25     e[cnt].to = to;
     26     e[cnt].cap = cap;
     27     h[from] = cnt;
     28     cnt++;
     29 }
     30 
     31 void ad(int from, int to, int cap)
     32 {
     33     add(from, to, cap);
     34     add(to, from, 0);
     35 }
     36 
     37 void bfs(int s)
     38 {
     39     memset(lv, -1, sizeof(lv));
     40     queue<int> q;
     41     lv[s] = 0;
     42     q.push(s);
     43     while(!q.empty())
     44     {
     45         int v = q.front(); q.pop();
     46         for(int i = h[v]; i >= 0; i = e[i].pre)
     47         {
     48             int cap = e[i].cap, to = e[i].to;
     49             if(cap > 0 && lv[to] < 0)
     50             {
     51                 lv[to] = lv[v] + 1;
     52                 q.push(to);
     53             }
     54         }
     55     }
     56 }
     57 
     58 int dfs(int v, int t, int f)
     59 {
     60     if(v == t) return f;
     61     for(int &i = it[v]; i >= 0; i = e[i].pre)
     62     {
     63         int &cap = e[i].cap, to = e[i].to;
     64         if(cap > 0 && lv[v] < lv[to])
     65         {
     66             int d = dfs(to, t, min(f, cap));
     67             if(d > 0)
     68             {
     69                 cap -= d;
     70                 e[i^1].cap += d;
     71                 return d;
     72             }
     73         }
     74     }
     75     return 0;
     76 }
     77 
     78 int Dinic(int s, int t)
     79 {
     80     int flow = 0;
     81     while(1)
     82     {
     83         bfs(s);
     84         if(lv[t] < 0) return flow;
     85         memcpy(it, h, sizeof(it));
     86         int f;
     87         while((f = dfs(s, t, INF)) > 0) flow += f;
     88     }
     89 }
     90 
     91 int a[11], G[11][11];
     92 int main(void)
     93 {
     94     int N, M;
     95     while(~scanf("%d %d", &N, &M))
     96     {
     97         if(!N) {puts("0"); continue;}
     98         memset(G, 0, sizeof(G));
     99         for(int i = 1; i <= M; i++)
    100         {
    101             int a, b;
    102             scanf("%d %d", &a, &b);
    103             G[a][b] = 1;
    104         }
    105 
    106         int ans = 0;
    107         for(int i = 0; i < N; i++) a[i] = i + 1;
    108         while(1)
    109         {
    110             init();
    111             int S = N + N + 1, T = S + 1;
    112             for(int i = 1; i <= N; i++) ad(S, i, 1), ad(N + i, T, 1);
    113             for(int i = 1; i <= N; i++)
    114                 for(int j = 0; j < N; j++)
    115                     if(!G[i][a[j]] && !G[i][a[(j+1)%N]])
    116                         ad(i, N + 1 + j, 1);
    117             ans = max(ans, Dinic(S, T));
    118             if(!next_permutation(a + 1, a + N)) break;
    119         }
    120         printf("%d
    ", N - ans);
    121     }
    122     return 0;
    123 }
    Aguin

    换匈牙利倒是快些。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 int N, cnt, h[11];
     7 
     8 struct edge
     9 {
    10     int to, pre;
    11 } e[1111];
    12 
    13 void init()
    14 {
    15     memset(h, -1, sizeof(h));
    16     cnt = 0;
    17 }
    18 
    19 void add(int from, int to)
    20 {
    21     e[cnt].pre = h[from];
    22     e[cnt].to = to;
    23     h[from] = cnt;
    24     cnt++;
    25 }
    26 
    27 // Hungary
    28 int lk[11], vis[11];
    29 bool dfs(int x)
    30 {
    31     for(int i = h[x]; i != -1; i = e[i].pre)
    32     {
    33         int to = e[i].to;
    34         if(!vis[to])
    35         {
    36             vis[to] = 1;
    37             if(lk[to] == -1 || dfs(lk[to]))
    38             {
    39                 lk[to] = x;
    40                 return true;
    41             }
    42         }
    43     }
    44     return false;
    45 }
    46 int Hungary()
    47 {
    48     int ret = 0;
    49     memset(lk, -1, sizeof(lk));
    50     for(int i = 1; i <= N; i++)
    51     {
    52         memset(vis, 0, sizeof(vis));
    53         if(dfs(i)) ret++;
    54     }
    55     return ret;
    56 }
    57 
    58 
    59 int a[11], G[11][11];
    60 int main(void)
    61 {
    62     int M;
    63     while(~scanf("%d %d", &N, &M))
    64     {
    65         if(!N) {puts("0"); continue;}
    66         memset(G, 0, sizeof(G));
    67         for(int i = 1; i <= M; i++)
    68         {
    69             int a, b;
    70             scanf("%d %d", &a, &b);
    71             G[a][b] = 1;
    72         }
    73 
    74         int ans = 0;
    75         for(int i = 0; i < N; i++) a[i] = i + 1;
    76         while(1)
    77         {
    78             init();
    79             for(int i = 1; i <= N; i++)
    80                 for(int j = 0; j < N; j++)
    81                     if(!G[i][a[j]] && !G[i][a[(j+1)%N]])
    82                         add(i, 1 + j);
    83             ans = max(ans, Hungary());
    84             if(!next_permutation(a + 1, a + N)) break;
    85         }
    86         printf("%d
    ", N - ans);
    87     }
    88     return 0;
    89 }
    Aguin

    1006 PowMod

    1007 Rigid Frameworks

    首先问题等价于求连通二分图数目。

    据鸟神所说,m行n列的桁架,在第i行第j列加约束,使得:

    ①第i行的所有竖向杆件平行。

    ②第j列的所有横向杆件平行。

    ③第i行所有竖向杆件和第j列所有横向杆件垂直。

    故只要对左边m个点,右边n个点建二分图,

    只要二分图连通,则所有横向杆件平行,所有竖向杆件平行,所有横向杆件与所有纵向杆件垂直,即为刚体。

    连通二分图计数问题,可以照着一般的连通图计数画葫芦。

    参考:gyz营员交流

    令$S(n, m)$为左边n个点,右边m个点的二分图数。

    $F(n, m)$为左边n个点,右边m个点的连通二分图数。

    $G(n, m) = S(n, m) - F(n, m)$

    固定二分图左边的第一个点,考虑有多少个点与其连通,

    $G(n, m) = sum_{i = 0}^{n - 1} sum_{j = 0, i + j eq m + n - 1}^{m} C_{n-1}^{i}C_{m}^{j} F(i+1, j) S(n-i-1, m-j)$

    而本题中对于i行j列的一个格子,可以选择不加约束,加左斜杠,加右斜杠。

    故$S(n, m) = 3 ^ {nm}$

    最后需要注意的是$F(n, m)$的边界条件。

     1 #include <iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 typedef long long LL;
     5 const LL mod = 1e9 + 7;
     6 LL S[11][11], F[11][11], G[11][11];
     7 LL c[11][11], p[111];
     8 
     9 int main(void)
    10 {
    11     p[0] = 1LL;
    12     for(int i = 1; i <= 100; i++) p[i] = p[i-1] * 3 % mod;
    13 
    14     for(int i = 0; i <= 10; i++) c[i][0] = c[i][i] = 1;
    15     for(int i = 1; i <= 10; i++)
    16         for(int j = 1; j < i; j++)
    17             c[i][j] = (c[i-1][j-1] + c[i-1][j]) % mod;
    18 
    19     F[0][1] = F[1][0] = 1;
    20     for(int i = 0; i <= 10; i++) S[0][i] = S[i][0] = 1;
    21     for(int i = 1; i <= 10; i++)
    22     for(int j = 1; j <= 10; j++)
    23     {
    24         for(int p = 0; p <= i - 1; p++)
    25         for(int q = 0; q <= j && p + q != i + j - 1; q++)
    26         G[i][j] = (G[i][j] + c[i-1][p] * c[j][q] % mod * F[p+1][q] % mod * S[i-p-1][j-q] % mod) % mod;
    27 
    28         S[i][j] = p[i*j];
    29         F[i][j] = (S[i][j] - G[i][j] + mod) % mod;
    30     }
    31 
    32 
    33     int m, n;
    34     while(~scanf("%d %d", &m, &n)) printf("%I64d
    ", F[m][n]);
    35     return 0;
    36 }
    Aguin

    1008 Shell Necklace

    1009 Solid Dominoes Tilings

    1010 Subway

    树同构,哈希一下就可以了。

    题解的哈希方法以前看csy说过。

    大概就是先找重心,每个点的孩子按哈希值排序算哈希值。

    然而一开始两个素数随便取老冲突,于是以sz作为第二关键字排,就稳了。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <vector>
      5 #include <algorithm>
      6 #include <map>
      7 using namespace std;
      8 typedef long long LL;
      9 const int maxn = 2e5 + 10;
     10 const LL P = 1e6 + 7, Q = 1e9 + 7;
     11 int N;
     12 
     13 map<string, int> M1, M2;
     14 string name[maxn];
     15 
     16 // edge
     17 int cnt, h[maxn];
     18 void init()
     19 {
     20     cnt = 0;
     21     memset(h, 0, sizeof(h));
     22 }
     23 struct edge
     24 {
     25     int to, pre;
     26 } e[maxn<<1];
     27 void add(int from, int to)
     28 {
     29     cnt++;
     30     e[cnt].pre = h[from];
     31     e[cnt].to = to;
     32     h[from] = cnt;
     33 }
     34 
     35 
     36 // Node
     37 struct node
     38 {
     39     int id, sz;
     40     LL h;
     41     node(int I, LL H, int S): id(I), h(H), sz(S) {}
     42     friend bool operator < (node A, node B)
     43     {
     44         if(A.h != B.h) return A.h < B.h;
     45         return A.sz < B.sz;
     46     }
     47 };
     48 
     49 
     50 // dfs
     51 int sz[maxn], M;
     52 vector<int> G;
     53 void dfs1(int x, int f)
     54 {
     55     sz[x] = 1;
     56     int tmp = 0;
     57     for(int i = h[x]; i; i = e[i].pre)
     58     {
     59         int to = e[i].to;
     60         if(to == f) continue;
     61         dfs1(to, x);
     62         sz[x] += sz[to];
     63         tmp = max(tmp, sz[to]);
     64     }
     65     tmp = max(tmp, N - sz[x]);
     66     if(tmp < M)
     67     {
     68         M = tmp;
     69         G.clear();
     70         G.push_back(x);
     71     }
     72     else if(tmp == M) G.push_back(x);
     73 }
     74 
     75 
     76 LL H[maxn];
     77 vector<node> v[maxn];
     78 void dfs2(int x, int f)
     79 {
     80     sz[x] = 1;
     81     v[x].clear();
     82     for(int i = h[x]; i; i = e[i].pre)
     83     {
     84         int to = e[i].to;
     85         if(to == f) continue;
     86         dfs2(to, x);
     87         sz[x] += sz[to];
     88         v[x].push_back(node(to, H[to], sz[to]));
     89     }
     90 
     91     sort(v[x].begin(), v[x].end());
     92     H[x] = 0;
     93     int sv = v[x].size();
     94     LL c = P;
     95     if(!sv) H[x] = 1;
     96     for(int i = 0; i < sv; i++)
     97     {
     98         H[x] = (H[x] + v[x][i].h * c) % Q;
     99         c = c * P % Q;
    100     }
    101 }
    102 
    103 void dfs3(int x1, int x2)
    104 {
    105     cout << name[x1] << ' ' << name[x2] << endl;
    106     int sv = v[x1].size();
    107     for(int i = 0; i < sv; i++) dfs3(v[x1][i].id, v[x2][i].id);
    108 }
    109 
    110 int main(void)
    111 {
    112 
    113     ios::sync_with_stdio(0);
    114 
    115     while(cin >> N)
    116     {
    117         init();
    118         M1.clear(), M2.clear();
    119         int num = 0;
    120 
    121         for(int i = 1; i < N; i++)
    122         {
    123             string a, b;
    124             cin >> a >> b;
    125             if(!M1[a]) M1[a] = ++num, name[num] = a;
    126             if(!M1[b]) M1[b] = ++num, name[num] = b;
    127             add(M1[a], M1[b]), add(M1[b], M1[a]);
    128         }
    129 
    130         M = N + 1;
    131         dfs1(1, 0);
    132         dfs2(G[0], 0);
    133         int rt1 = G[0];
    134 
    135         for(int i = 1; i < N; i++)
    136         {
    137             string a, b;
    138             cin >> a >> b;
    139             if(!M2[a]) M2[a] = ++num, name[num] = a;
    140             if(!M2[b]) M2[b] = ++num, name[num] = b;
    141             add(M2[a], M2[b]), add(M2[b], M2[a]);
    142         }
    143 
    144         M = N + 1;
    145         dfs1(N + 1, 0);
    146         dfs2(G[0], 0);
    147         int rt2 = G[0];
    148         if(H[rt1] != H[G[0]]) dfs2(G[1], 0), rt2 = G[1];
    149 
    150         dfs3(rt1, rt2);
    151 
    152     }
    153     return 0;
    154 }
    Aguin

    1011 tetrahedron

  • 相关阅读:
    Java 设计模式之单例
    CentOS 下安装配置Hadoop
    Linux 修改IP地址和DNS
    Hibernate 主配置文件详解
    HTTP 协议细节
    Java 设计模式之工厂
    mysqldump备份与还原
    [小技巧]windows时间同步
    关于反射
    XHTML、DTD和Web Services
  • 原文地址:https://www.cnblogs.com/Aguin/p/5693226.html
Copyright © 2011-2022 走看看