CF132E Bits of merry old England

解:略一思索:网络流啊!(别问我是怎么想到的......)

发现跟志愿者招募有点像。于是把图建一下,在下面开一条通道,但是每个点又都要经过,这时我们就无脑上下界一波。

通道向点连边,有费用。每个点向它下一次出现的点连边,费用0。每个点还向通道连边,费用0。

上下界费用流跑一下就出来费用了。然后是输出方案,看哪些边有流量,直接模拟。

 

  1 #include <bits/stdc++.h>
  2 
  3 const int N = 1010, INF = 0x3f3f3f3f;
  4 
  5 struct Edge {
  6     int nex, v, c, len;
  7     Edge(int Nex = 0, int V = 0, int C = 0, int L = 0) {
  8         nex = Nex;
  9         v = V;
 10         c = C;
 11         len = L;
 12     }
 13 }edge[1000000]; int tp = 1;
 14 
 15 int X[N];
 16 
 17 struct Node {
 18     int p, v;
 19     bool f; /// 0 print  1 change
 20     Node(int P = 0, int V = 0, bool F = 0) {
 21         p = P;
 22         v = V;
 23         f = F;
 24     }
 25     inline void out() {
 26         if(!f) {
 27             printf("print("); putchar('a' + p - 1); printf(")\n");
 28         }
 29         else {
 30             putchar('a' + p - 1); printf("=%d\n", X[v]);
 31         }
 32         return;
 33     }
 34 }stk[N]; int top;
 35 
 36 int xx, Last[N], nex[N], in[N], e[N], tag[N];
 37 int n, m, a[N], val[N], pre[N], vis[N], flow[N], d[N];
 38 std::queue<int> Q;
 39 
 40 inline void Max(int &a, const int &b) {
 41     a < b ? a = b : 0;
 42     return;
 43 }
 44 
 45 inline void add(int x, int y, int z, int w) {
 46 //    printf("add : %d %d %d %d\n", x, y, z, w);
 47     edge[++tp] = Edge(e[x], y, z, w);
 48     e[x] = tp;
 49     edge[++tp] = Edge(e[y], x, 0, -w);
 50     e[y] = tp;
 51     return;
 52 }
 53 
 54 inline bool SPFA(int s, int t) {
 55     static int Time = 0; ++Time;
 56     memset(d, 0x3f, sizeof(d));
 57     Q.push(s);
 58     vis[s] = Time;
 59     flow[s] = INF;
 60     d[s] = 0;
 61     while(!Q.empty()) {
 62         int x = Q.front();
 63         Q.pop();
 64         vis[x] = 0;
 65 //        printf("  x = %d  d[x] = %d \n", x, d[x]);
 66         for(int i = e[x]; i; i = edge[i].nex) {
 67             int y = edge[i].v;
 68             if(d[y] > d[x] + edge[i].len && edge[i].c) {
 69                 d[y] = d[x] + edge[i].len;
 70 //                printf("    y = %d  d[y] = %d \n", y, d[y]);
 71                 flow[y] = std::min(flow[x], edge[i].c);
 72                 pre[y] = i;
 73                 if(vis[y] != Time) {
 74                     vis[y] = Time;
 75                     Q.push(y);
 76                 }
 77             }
 78         }
 79     }
 80     return d[t] < INF;
 81 }
 82 
 83 inline void update(int s, int t) {
 84     int f = flow[t];
 85 //    printf("update : %d ", t);
 86     while(t != s) {
 87         int i = pre[t];
 88         edge[i].c -= f;
 89         edge[i ^ 1].c += f;
 90         t = edge[i ^ 1].v;
 91 //        printf("%d ", t);
 92     }
 93 //    printf("\n");
 94     return;
 95 }
 96 
 97 inline int solve(int s, int t, int &cost) {
 98     int ans = 0; cost = 0;
 99 //    printf("solve : %d %d \n", s, t); int i = 0;
100     while(SPFA(s, t)) {
101 //        printf("loop : %d flow = %d d = %d \n", ++i, flow[t], d[t]);
102         ans += flow[t];
103         cost += flow[t] * d[t];
104         update(s, t);
105     }
106 //    printf("ans = %d cost = %d\n", ans, cost);
107     return ans;
108 }
109 
110 /*
111 7 2
112 1 2 2 4 2 1 2
113 ------------- 11 4
114 6 3
115 1 2 3 1 2 3
116 -------------  9 4
117 */
118 
119 int main() {
120     scanf("%d%d", &n, &m);
121     for(int i = 1; i <= n; i++) {
122         scanf("%d", &a[i]);
123         int x = a[i];
124         while(x) {
125             x -= x & (-x);
126             val[i]++;
127         }
128         X[i] = a[i];
129     }
130     std::sort(X + 1, X + n + 1);
131     xx = std::unique(X + 1, X + n + 1) - X - 1;
132 //    printf("xx = %d \n", xx);
133     for(int i = 1; i <= n; i++) {
134         a[i] = std::lower_bound(X + 1, X + xx + 1, a[i]) - X;
135 //        printf("a %d = %d \n", i, a[i]);
136     }
137     for(int i = n; i >= 1; i--) {
138         nex[i] = Last[a[i]];
139         Last[a[i]] = i;
140     }
141     /// add edge
142     
143     int s = n * 3 + 2, t = s + 1, ss = s + 2, tt = s + 3;
144     for(int i = 1; i <= n; i++) {
145 //        add(i, i + n, [1, 1], 0);
146         in[i + n]++; in[i]--;
147         add(i + 2 * n, i, 1, val[i]);
148         add(i + n, i + 1 + 2 * n, 1, 0);
149         add(i + 2 * n, i + 1 + 2 * n, INF, 0); 
150         if(nex[i]) {
151             add(i + n, nex[i], 1, 0);
152 //            printf("nex %d = %d  add(%d %d)\n", i, nex[i], i + n, nex[i]);
153         }
154     }
155     add(s, 1 + 2 * n, m, 0);
156     add(n + 1 + 2 * n, t, m, 0);
157     int Ck = tp;
158     add(t, s, INF, 0);
159     for(int i = 1; i <= t; i++) {
160         if(in[i]) {
161             if(in[i] > 0) {
162                 add(ss, i, in[i], 0);
163             }
164             else  {
165                 add(i, tt, -in[i], 0);
166             }
167         }
168     }
169     
170     int cost1 = 0, cost2 = 0;
171     solve(ss, tt, cost1);
172     for(int i = Ck + 1; i <= tp; i++) {
173         edge[i].c = 0;
174     }
175     solve(s, t, cost2);
176     
177     // get ways
178     for(int i = 1; i <= m; i++) {
179         Q.push(i);
180     }
181     for(int j = 1; j <= n; j++) {
182         int x = j + 2 * n;
183         for(int i = e[x]; i; i = edge[i].nex) {
184             int y = edge[i].v;
185             if(y == j && edge[i ^ 1].c) {
186                 /// a num -> a[j]
187                 tag[j] = Q.front();
188                 Q.pop();
189                 stk[++top] = Node(tag[j], a[j], 1);
190                 break;
191             }
192         }
193 //        printf("tag[j] = %d \n", tag[j]);
194         stk[++top] = Node(tag[j], 0, 0);
195         x = j + n;
196         for(int i = e[x]; i; i = edge[i].nex) {
197             int y = edge[i].v;
198             if(y == nex[j] && edge[i ^ 1].c) {
199                 tag[nex[j]] = tag[j];
200                 break;
201             }
202             if(y == j + 1 + 2 * n && edge[i ^ 1].c) {
203                 /// return queue
204                 Q.push(tag[j]);
205                 break;
206             }
207         }
208     }
209     
210     printf("%d %d\n", top, cost1 + cost2);
211     for(int i = 1; i <= top; i++) stk[i].out();
212     return 0;
213 }
AC代码

 

posted @ 2019-03-16 16:00  huyufeifei  阅读(219)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜