[BeiJing wc2012]连连看

题目链接 费用流板子+拆点

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 inline int read()
  5 {
  6     int x=0,f=1;char ch=getchar();
  7     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  8     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
  9     return x*f;
 10 }
 11 
 12 
 13 /********************************************************************/
 14 
 15 struct ZKM_MinCostMaxFlow{
 16     const static int maxn = 1e5+50;
 17     const static int maxE = 1e5+50;
 18     const static int INF = 0xfffffff;
 19 
 20     struct Edge{
 21         int to, next, cap, flow, cost;
 22         Edge(int _to = 0, int _next = 0, int _cap = 0, int _flow = 0, int _cost = 0):
 23             to(_to), next(_next), cap(_cap), flow(_flow), cost(_cost){}
 24     }edge[maxE*2];
 25 
 26     int head[maxn], tot;
 27     int cur[maxn], dis[maxn];
 28     bool vis[maxn];
 29     int ss, tt, N;
 30     int min_cost, max_flow;
 31     void init(int N){
 32         tot = 0;
 33         for(int i = 0;i < N;i++) head[i] = -1;
 34     }
 35     int addedge(int u, int v, int cap, int cost){
 36         edge[tot] = Edge(v, head[u], cap, 0, cost);
 37         int rs = tot;
 38         head[u] = tot++;
 39         edge[tot] = Edge(u, head[v], 0, 0, -cost);
 40         head[v] = tot++;
 41         return rs;
 42     }
 43     int aug(int u, int flow){
 44         if(u == tt) return flow;
 45         vis[u] = true;
 46         for(int i = cur[u];i != -1;i = edge[i].next){
 47             int v = edge[i].to;
 48             if(edge[i].cap > edge[i].flow && !vis[v] && dis[u] == dis[v] + edge[i].cost){
 49                 int tmp = aug(v, min(flow, edge[i].cap - edge[i].flow));
 50                 edge[i].flow += tmp;
 51                 edge[i^1].flow -= tmp;
 52                 cur[u] = i;
 53                 if(tmp) return tmp;
 54             }
 55         }
 56         return 0;
 57     }
 58     bool modify_label(){
 59         int d = INF;
 60         for(int u = 0;u < N;u++){
 61             if(vis[u]){
 62                 for(int i = head[u];i != -1;i = edge[i].next){
 63                     int v = edge[i].to;
 64                     if(edge[i].cap > edge[i].flow && !vis[v]){
 65                         d = min(d, dis[v]+edge[i].cost - dis[u]);
 66                     }
 67                 }
 68             }
 69         }
 70         if(d == INF) return false;
 71         for(int i = 0;i < N;i++){
 72             if(vis[i]){
 73                 vis[i] = false;
 74                 dis[i] += d;
 75             }
 76         }
 77         return true;
 78     }
 79 
 80     pair<int, int> mincostmaxflow(int start, int ed, int n){
 81         ss = start, tt = ed, N = n;
 82         min_cost = max_flow = 0;
 83         for(int i = 0;i < n;i++) dis[i] = 0;
 84         while(1){
 85             for(int i = 0;i < n;i++) cur[i] = head[i];
 86             while(1){
 87                 for(int i = 0;i < n;i++) vis[i] = false;
 88                 int tmp = aug(ss, INF);
 89                 if(tmp == 0) break;
 90                 max_flow += tmp;
 91                 min_cost += tmp*dis[ss];
 92             }
 93             if(!modify_label()) break;
 94         }
 95         return make_pair( max_flow, min_cost );
 96     }
 97 }solver;
 98 
 99 int gcd(int x, int y){
100     if(y == 0) return x;
101     else return gcd(y, x%y);
102 }
103 
104 bool check(int x, int y){
105     if(x == y) return false;
106     if(x < y)  swap(x, y);
107     int t = sqrt(x*x-y*y);
108     if(t*t != x*x-y*y) return false;
109     if(gcd(y, t) != 1) return false;
110     return true;
111 }
112 
113 int main(){
114     int a, b;
115     a = read(); b = read();
116     solver.init(b*2+5);
117     for(int i = a;i <= b;i++){
118         for(int j = a;j <= b;j++){
119             if(check(i, j)){
120                 solver.addedge(i, j+b, 1, -i-j);
121             }
122         }
123         solver.addedge(b*2+1, i, 1, 0);     //拆点
124         solver.addedge(i+b, b*2+2, 1, 0);   //拆点
125     }
126     pair<int, int> ans = solver.mincostmaxflow(b*2+1, b*2+2, b*2+5);
127     printf("%d %d\n", ans.first/2, -ans.second/2);
128     return 0;
129 }

 

posted @ 2018-10-08 19:59  ouyang_wsgwz  阅读(175)  评论(0编辑  收藏  举报