zoukankan      html  css  js  c++  java
  • CodeForces Round #290 Fox And Dinner

    而是Div2的最后一题,当时打比赛的时候还不会最大流。自己能够把它写出来然后1A还是很开心的。

    题意:

    有n个不小于2的整数,现在要把他们分成若干个圈。在每个圈中,数字的个数不少于3个,而且相邻的两个数之和是质数。

    分析:

    因为每个数都不小于2,所以相加得到的质数一定是奇数,那么在某个圈中,一定是奇偶相间的。

    也就是 奇数相邻的两个数是偶数,偶数相邻的两个数是奇数。

    所以一个圈中的数字一定是偶数个,所有的输入中也必须是偶数和奇数的个数相同才可能有解。

    这转化为了二分图匹配,其中X是奇数,Y是偶数,如果X和Y中的两个数加起来是质数,则连一条容量为1的边。

    因为每个奇数的两边是偶数,所以将X中的点与源点连一条容量为2的边。

    同样地,将Y中的点与汇点连一条容量为2的边。

    求一次最大流,如果满载也就是流量为n的话,说明有解。

    输出解:可以根据求解最大流的时候,找到的路径,再建一个图,然后DFS找环。

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 const int maxn = 200 + 10;
      6 const int INF = 1000000000;
      7 
      8 struct Edge
      9 {
     10     int from, to, cap, flow;
     11     Edge(int u, int v, int c, int f): from(u), to(v), cap(c), flow(f) {}
     12 };
     13 
     14 struct EdmondsKarp
     15 {
     16     int n, m;
     17     vector<Edge> edges;
     18     vector<int> G[maxn];
     19     int a[maxn];    //可改进量
     20     int p[maxn];    //上一条弧
     21 
     22     void Init(int n)
     23     {
     24         for(int i = 0; i < n; ++i) G[i].clear();
     25         edges.clear();
     26     }
     27 
     28     void AddEdge(int from, int to, int cap)
     29     {
     30         edges.push_back(Edge(from, to, cap, 0));
     31         edges.push_back(Edge(to, from, 0, 0));
     32         m = edges.size();
     33         G[from].push_back(m-2);
     34         G[to].push_back(m-1);
     35     }
     36 
     37     int MaxFlow(int s, int t)
     38     {
     39         int flow = 0;
     40         for(;;)
     41         {
     42             memset(a, 0, sizeof(a));
     43             queue<int> Q;
     44             Q.push(s);
     45             a[s] = INF;
     46             while(!Q.empty())
     47             {
     48                 int x = Q.front(); Q.pop();
     49                 for(int i = 0; i < G[x].size(); ++i)
     50                 {
     51                     Edge& e = edges[G[x][i]];
     52                     if(!a[e.to] && e.cap > e.flow)
     53                     {
     54                         a[e.to] = min(a[x], e.cap - e.flow);
     55                         p[e.to] = G[x][i];
     56                         Q.push(e.to);
     57                     }
     58                 }
     59                 if(a[t]) break;
     60             }
     61             if(!a[t]) break;
     62             for(int u = t; u != s; u = edges[p[u]].from)
     63             {
     64                 edges[p[u]].flow +=  a[t];
     65                 edges[p[u]^1].flow -= a[t];
     66             }
     67             flow += a[t];
     68         }
     69         return flow;
     70     }
     71 }g;
     72 
     73 int a[maxn], odd[maxn], even[maxn], p1, p2;
     74 vector<int> G[maxn], ans[maxn];
     75 const int maxp = 20000;
     76 bool prime[maxp + 10], vis[maxn];
     77 
     78 void prime_table()
     79 {
     80     int m = sqrt(maxp + 0.5);
     81     for(int i = 2; i <= m; ++i) if(!prime[i])
     82         for(int j = i*i; j <= maxp; j += i) prime[j] = true;
     83 }
     84 
     85 void find_circle(int cnt, int u)
     86 {
     87     ans[cnt].push_back(u);
     88     vis[u] = true;
     89     for(int i = 0; i < G[u].size(); ++i)
     90     {
     91         int v = G[u][i];
     92         if(!vis[v]) find_circle(cnt, v);
     93     }
     94 }
     95 
     96 int main()
     97 {
     98     //freopen("in.txt", "r", stdin);
     99 
    100     int n;
    101     scanf("%d", &n);
    102     g.Init(n+2);
    103     for(int i = 1; i <= n; ++i)
    104     {
    105         scanf("%d", &a[i]);
    106         if(a[i] & 1) odd[p1++] = i;
    107         else even[p2++] = i;
    108     }
    109     if(p1 != p2) { puts("Impossible"); return 0; }//奇数和偶数个数不同
    110 
    111     for(int i = 0; i < p1; ++i)
    112     {
    113         g.AddEdge(0, odd[i], 2);
    114         g.AddEdge(even[i], n+1, 2);
    115     }
    116 
    117     prime_table();
    118     for(int i = 0; i < p1; ++i)
    119         for(int j = 0; j < p1; ++j)
    120             if(!prime[ a[odd[i]] + a[even[j]] ])
    121                 g.AddEdge(odd[i], even[j], 1);
    122 
    123     int flow = g.MaxFlow(0, n+1);
    124     if(flow != n) { puts("Impossible"); return 0; }
    125 
    126     for(int i = 0; i < g.edges.size(); ++i)
    127     {//为了寻找路径,建一个新图
    128         Edge& e = g.edges[i];
    129         if(e.cap == 1 && e.flow == 1)
    130         {
    131             G[e.from].push_back(e.to);
    132             G[e.to].push_back(e.from);
    133         }
    134     }
    135 
    136     int cnt = 0;
    137     for(int i = 1; i <= n; ++i) if(!vis[i]) find_circle(cnt++, i);
    138 
    139     printf("%d
    ", cnt);
    140     for(int i = 0; i < cnt; ++i)
    141     {
    142         printf("%d %d", ans[i].size(), ans[i][0]);
    143         for(int j = 1; j < ans[i].size(); ++j) printf(" %d", ans[i][j]);
    144         puts("");
    145     }
    146 
    147     return 0;
    148 }
    代码君
  • 相关阅读:
    POJ3094 UVALive3594 HDU2734 ZOJ2812 Quicksum【进制】
    UVALive5583 UVA562 Dividing coins
    POJ1979 HDU1312 Red and Black【DFS】
    POJ1979 HDU1312 Red and Black【DFS】
    POJ2386 Lake Counting【DFS】
    POJ2386 Lake Counting【DFS】
    HDU4394 Digital Square
    HDU4394 Digital Square
    UVA213 UVALive5152 Message Decoding
    UVA213 UVALive5152 Message Decoding
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4286931.html
Copyright © 2011-2022 走看看