bzoj 3996 最小割
公式推出来后想了半天没思路,居然A是01矩阵。。。。。
如果一个问题是求最值,并那么尝试先将所有可能收益加起来,然后矛盾部分能否用最小割表达(本题有两个矛盾,第一个是选还是不选,第二个是i,j有一个不选,就不能获得bij的收益)。
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #define N 510 5 #define S N+N*N 6 #define E S*10 7 #define oo 0x3f3f3f3f 8 #define fill(a,l,r,v) memset(a+l,v,sizeof(a[0])*(r-l+1)) 9 using namespace std; 10 11 struct Edge { 12 int u, v, f; 13 Edge(){} 14 Edge( int u, int v, int f ):u(u),v(v),f(f){} 15 }; 16 struct Dinic { 17 int n, src, dst; 18 int head[S], next[E], etot; 19 Edge edge[E]; 20 int dep[S], cur[S], qu[S], bg, ed; 21 22 void init( int n, int src, int dst ) { 23 this->n = n; 24 this->src = src; 25 this->dst = dst; 26 fill( head, 0, n, 0x3f ); 27 } 28 void adde( int u, int v, int f ) { 29 next[etot]=head[u], head[u]=etot; 30 edge[etot++] = Edge(u,v,f); 31 next[etot]=head[v], head[v]=etot; 32 edge[etot++] = Edge(v,u,0); 33 } 34 bool bfs() { 35 fill(dep,0,n,0); 36 qu[bg=ed=1] = src; 37 dep[src] = 1; 38 while( bg<=ed ) { 39 int u=qu[bg++]; 40 for( int t=head[u]; t!=oo; t=next[t] ) { 41 Edge &e = edge[t]; 42 if( e.f && !dep[e.v] ) { 43 qu[++ed] = e.v; 44 dep[e.v] = dep[e.u]+1; 45 } 46 } 47 } 48 return dep[dst]; 49 } 50 int dfs( int u, int a ) { 51 if( u==dst || a==0 ) return a; 52 int remain=a, past=0, na; 53 if( cur[u]==-1 ) cur[u]=head[u]; 54 for( int &t=cur[u]; t!=oo; t=next[t] ) { 55 Edge &e = edge[t]; 56 Edge &ve = edge[t^1]; 57 if( e.f && dep[e.v]==dep[e.u]+1 && (na=dfs(e.v,min(e.f,remain))) ) { 58 remain -= na; 59 past += na; 60 e.f -= na; 61 ve.f += na; 62 if( !remain ) break; 63 } 64 } 65 return past; 66 } 67 int flow() { 68 int rt = 0; 69 while( bfs() ) { 70 fill( cur, 0, n, -1 ); 71 rt += dfs(src,oo); 72 } 73 return rt; 74 } 75 }D; 76 77 int n, src, dst, idc; 78 int main() { 79 scanf( "%d", &n ); 80 src = 0; 81 dst = n*n+n+1; 82 idc = 0; 83 D.init( dst, src, dst ); 84 int tot=0; 85 for( int i=1; i<=n; i++ ) 86 for( int j=1; j<=n; j++ ) { 87 int bij; 88 scanf( "%d", &bij ); 89 idc++; 90 D.adde( src, idc, bij ); 91 D.adde( idc, i, oo ); 92 D.adde( idc, j, oo ); 93 tot += bij; 94 } 95 for( int i=1; i<=n; i++ ) { 96 int ci; 97 scanf( "%d", &ci ); 98 D.adde( src, i, 0 ); 99 D.adde( i, dst, ci ); 100 } 101 printf( "%d\n", tot-D.flow() ); 102 }
——————
我的最小割好慢。。。