挺好的一道题目,我的做法是kmp+Dinic网络流。
kmp求子串在P中出现的次数,从而计算love值。
网络流主要用来处理最优解。
case2中p1的love值是8,p2的love值是7,最终T包含p1和p2,hate值也仅仅算一次。
这个题目难点在于思考为什么网络流的解法是合理,可以反证。从而导出最优解等于love的总和-最大流。
建图方法:
source连接p,初始容量为love值;
p连接s,初始容量为INF;
s连接destination,容量为hate值。
在最优解中,如果s到des的流量小于容量,则证明包含s的p都不被选择。即减去p的容量和。如果流量大于等于容量,则证明该直接去掉hate值。
1 /* 3505 */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #include <vector> 9 #include <deque> 10 #include <algorithm> 11 #include <cstdio> 12 #include <cmath> 13 #include <ctime> 14 #include <cstring> 15 #include <climits> 16 #include <cctype> 17 #include <cassert> 18 #include <functional> 19 #include <iterator> 20 #include <iomanip> 21 using namespace std; 22 //#pragma comment(linker,"/STACK:102400000,1024000") 23 24 #define sti set<int> 25 #define stpii set<pair<int, int> > 26 #define mpii map<int,int> 27 #define vi vector<int> 28 #define pii pair<int,int> 29 #define vpii vector<pair<int,int> > 30 #define rep(i, a, n) for (int i=a;i<n;++i) 31 #define per(i, a, n) for (int i=n-1;i>=a;--i) 32 #define clr clear 33 #define pb push_back 34 #define mp make_pair 35 #define fir first 36 #define sec second 37 #define all(x) (x).begin(),(x).end() 38 #define SZ(x) ((int)(x).size()) 39 #define lson l, mid, rt<<1 40 #define rson mid+1, r, rt<<1|1 41 42 typedef struct { 43 int l, h, len; 44 char s[54]; 45 int nxt[54]; 46 47 void getnext() { 48 int i = 0, j = -1; 49 50 nxt[0] = -1; 51 while (i < len) { 52 if (j==-1 || s[i]==s[j]) { 53 ++i; 54 ++j; 55 nxt[i] = j; 56 } else { 57 j = nxt[j]; 58 } 59 } 60 } 61 62 int kmp(char *d) { 63 int dlen = strlen(d); 64 int i = 0, j =0; 65 int ret = 0; 66 67 while (i < dlen) { 68 if (d[i] == s[j]) { 69 ++i; 70 ++j; 71 } else { 72 j = nxt[j]; 73 if (j == -1) { 74 j = 0; 75 ++i; 76 } 77 } 78 if (j == len) { 79 ++ret; 80 j = nxt[j]; 81 } 82 } 83 84 return ret; 85 } 86 87 } node_t; 88 89 typedef struct { 90 int v, f, nxt; 91 } edge_t; 92 93 const int INF = 0x3f3f3f3f; 94 const int maxn = 155; 95 const int maxv = maxn * 2; 96 const int maxl = 1005; 97 const int maxe = 1e5+5; 98 node_t nd[maxn]; 99 bool M[maxn][maxn]; 100 int score[maxn]; 101 int head[maxv], head_[maxv]; 102 edge_t E[maxe]; 103 int dis[maxv]; 104 int Q[maxv]; 105 char s[maxl]; 106 int nxt[maxl]; 107 int sn, pn, m; 108 109 int calc(int k) { 110 int ret = 0, cnt; 111 112 rep(i, 1, sn+1) { 113 cnt = nd[i].kmp(s); 114 if (cnt) { 115 ret += nd[i].l * cnt; 116 M[k][i] = true; 117 } 118 } 119 120 return ret; 121 } 122 123 void init() { 124 m = 0; 125 memset(head, -1, sizeof(head)); 126 memset(M, false, sizeof(M)); 127 } 128 129 void addEdge(int u, int v, int f) { 130 E[m].v = v; 131 E[m].f = f; 132 E[m].nxt = head[u]; 133 head[u] = m++; 134 135 E[m].v = u; 136 E[m].f = 0; 137 E[m].nxt = head[v]; 138 head[v] = m++; 139 } 140 141 bool bfs(int s, int t) { 142 int l = 0, r = 0; 143 int u, v, k; 144 145 Q[r++] = s; 146 memset(dis, 0, sizeof(dis)); 147 dis[s] = 1; 148 149 while (l < r) { 150 u = Q[l++]; 151 for (k=head[u]; k!=-1; k=E[k].nxt) { 152 v = E[k].v; 153 if (!dis[v] && E[k].f) { 154 dis[v] = dis[u] + 1; 155 if (v == t) 156 return false; 157 Q[r++] = v; 158 } 159 } 160 } 161 162 return true; 163 } 164 165 int dfs(int u, int t, int val) { 166 if (u==t || val==0) 167 return val; 168 169 int ret = 0; 170 int v, tmp; 171 172 for (int& k=head_[u]; k!=-1; k=E[k].nxt) { 173 v = E[k].v; 174 if (E[k].f && dis[v]==dis[u]+1 && (tmp=dfs(v, t, min(val, E[k].f)))>0) { 175 E[k].f -= tmp; 176 E[k^1].f += tmp; 177 ret += tmp; 178 val -= tmp; 179 if (val == 0) 180 return ret; 181 } 182 } 183 184 return ret; 185 } 186 187 int Dinic(int s, int t) { 188 int ret = 0, tmp; 189 190 while (1) { 191 if (bfs(s, t)) 192 break; 193 194 memcpy(head_, head, sizeof(head)); 195 while (1) { 196 tmp = dfs(s, t, INF); 197 if (tmp == 0) 198 break; 199 ret += tmp; 200 } 201 } 202 203 return ret; 204 } 205 206 void Build() { 207 int s = 0; 208 int t = maxv - 1; 209 210 rep(i, 1, sn+1) { 211 addEdge(i, t, nd[i].h); 212 } 213 214 rep(i, 1, pn+1) { 215 addEdge(s, sn+i, score[i]); 216 rep(j, 1, sn+1) { 217 if (M[i][j]) 218 addEdge(sn+i, j, INF); 219 } 220 } 221 } 222 223 int solve() { 224 int ret = 0; 225 226 rep(i, 1, pn+1) { 227 scanf("%s", s); 228 score[i] = calc(i); 229 ret += score[i]; 230 } 231 232 Build(); 233 int tmp = Dinic(0, maxv-1); 234 ret -= tmp; 235 #ifndef ONLINE_JUDGE 236 printf("maxflow = %d ", tmp); 237 #endif 238 239 return ret; 240 } 241 242 int main() { 243 ios::sync_with_stdio(false); 244 #ifndef ONLINE_JUDGE 245 freopen("data.in", "r", stdin); 246 freopen("data.out", "w", stdout); 247 #endif 248 249 int t; 250 int ans; 251 252 scanf("%d", &t); 253 rep(tt, 1, t+1) { 254 init(); 255 scanf("%d %d", &sn, &pn); 256 rep(i, 1, sn+1) { 257 scanf("%d %d %s", &nd[i].l, &nd[i].h, nd[i].s); 258 nd[i].len = strlen(nd[i].s); 259 nd[i].getnext(); 260 } 261 ans = solve(); 262 printf("Case %d: %d ", tt, ans); 263 } 264 265 #ifndef ONLINE_JUDGE 266 printf("time = %d. ", (int)clock()); 267 #endif 268 269 return 0; 270 }