HDU3395 Special Fish 费用流

来源:互联网 发布:vmware虚拟机网络桥接 编辑:程序博客网 时间:2024/06/08 01:19

最近没怎么写博客了, 果断是觉得以前写博客的自己好sb。。。

看到这么丧心病狂的题目背景, 突然就想写写了。。


题意:

有一群丧心病狂的莫名物种的鱼, 每个都认为自己是male( 特么地这样能科学?? ), 然后每条鱼都有一个val值, 并且有可能会攻击它认为是female的鱼, 更加丧心病狂的是攻击了之后会怀孕惊恐惊恐, 很想问下这是什么攻击。   怀孕之后会产下一个价值为两个父亲的价值XOR的后代, 每条鱼最多只能XX别人一次, 也最多只能被别人XX一次, 然后求产下后代val值的和的最大值。


思路:

将一个点拆成两个点(1~n和n+1~2n), 分别表示XX别人和被别人XX,如果i能XXj 就向i到j+n连一条费用为-val[i]^val[j], 流量为1的边,如果这条边有流量的话就表示iXXj,

源点S = 0, 汇点T = 2 * n + 1, 向S到i连费用为0, 流量为1的边, 向i+n到T连费用为0, 流量1的边。

然后求出最小费用流就可以了。 刚开始以为要满流, wa了几次之后才发现不用满流, 每次找到最短路更新的最小费用的时候顺便更新下答案就可以了。


#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;#define mxn 302#define mxe 100020#define inf 0x3f3f3f3fstruct edge {int u, v, cap, flow, cost, nxt;edge() {}edge( int u, int v, int cap, int flow, int cost, int nxt ):u( u ), v( v ), cap( cap ), flow( flow ), cost( cost ), nxt( nxt ) {}};struct mcmf {edge e[mxe];int cc, fst[mxn], p[mxn], d[mxn], a[mxn];bool in[mxn];void init() {memset( fst, -1, sizeof( fst ) );cc = 0;}void add( int u, int v, int cap, int cost ) {e[cc] = edge( u, v, cap, 0, cost, fst[u] );fst[u] = cc++;e[cc] = edge( v, u, 0, 0, -cost, fst[v] );fst[v] = cc++;}int bf( int s, int t, int &mf, int &mc ) {memset( d, 0x3f, sizeof( d ) );memset( in, 0, sizeof( in ) );d[s] = 0, a[s] = inf, in[s] = 1, p[s] = 0;queue<int> q;q.push( s );while( !q.empty() ) {int x = q.front(); q.pop();in[x] = 0;for( int i = fst[x]; ~i; i = e[i].nxt ) {int v = e[i].v;if( e[i].cap > e[i].flow && d[v] > d[x] + e[i].cost ) {d[v] = d[x] + e[i].cost;p[v] = i;a[v] = min( a[x], e[i].cap - e[i].flow );if( !in[v] )in[v] = 1, q.push( v );}}}if( d[t] == inf )return 0;mf += a[t];mc += a[t] * d[t];int u = t;while( u != s ) {e[p[u]].flow += a[t];e[p[u]^1].flow -= a[t];u = e[p[u]].u;}return 1;}int go( int s, int t ) {int res = 0;int mf = 0, mc = 0;while( bf( s, t, mf, mc ) ) {res = min( res, mc );}return res;}}go;int n, a[mxn], S, T;char s[mxn];int main() {while( scanf( "%d", &n ) != EOF && n ) {S = 0, T = 2 * n + 1;for( int i = 1; i <= n; ++i )scanf( "%d", &a[i] );go.init();for( int i = 1; i <= n; ++i ) {scanf( "%s", s + 1 );for( int j = 1; j <= n; ++j )if( s[j] == '1' )go.add( i, j + n, 1, - ( a[i] ^ a[j] ) );go.add( S, i, 1, 0 );go.add( i + n, T, 1, 0 );}printf( "%d\n", - go.go( S, T ) );}return 0;}


0 0
原创粉丝点击