题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4307
【题意】
求一个1*N的0、1向量A,使得D = (A*B - C)*A' 最大,B,C给定元素非负,A'表示A的转置。
【分析】
sum(Ai * Bij * Aj) - sum(Ai * Ci)
= sum(Bij)
- {sum((1-Ai) * Bi) + sum(Ai * Bij * (1-Aj)) + sum(Ai * Ci)}
Bi表示第i行和,Ai = {0,1}
如此求红色部分的最小值即可。
观察公式可得,Ai取值0、1,套用最小割模型,加边:(s,i,Bi),(i,t,Ci),(j,i,Bij),求最小割即可。
dinic:531MS
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 #include<vector> 6 #define LL long long 7 8 using namespace std; 9 10 const int maxn = 1011; 11 const int maxm = 4100010; 12 const LL inf = 999999999999; 13 14 15 16 17 struct Dinic{ 18 int node, src, dest, ne; 19 int head[maxn], work[maxn], dist[maxn],Q[maxn]; 20 LL flow[maxm]; 21 int pnt[maxm], nxt[maxm]; 22 23 24 void init(int _node, int _src, int _dest) 25 { 26 node = _node; 27 src = _src; 28 dest = _dest; 29 for (int i=0;i<node;i++) 30 { 31 head[i] = -1; 32 } 33 ne = 0; 34 } 35 void add(int u,int v, LL c1,LL c2) 36 { 37 pnt[ne] = v, flow[ne] = c1, nxt[ne] = head[u], head[u] = ne++; 38 pnt[ne] = u, flow[ne] = c2, nxt[ne] = head[v], head[v] = ne++; 39 40 } 41 bool dinic_bfs(void) 42 { 43 int i,u,v,l,r=0; 44 for(int i=0;i<node;i++) dist[i]=-1; 45 dist[Q[r++]=src]=0; 46 for(l=0;l<r;l++) for(i=head[u=Q[l]];i>=0;i=nxt[i]) 47 if(flow[i] && dist[v=pnt[i]]<0) 48 { 49 dist[Q[r++]=v]=dist[u]+1; 50 if(v==dest) return 1; 51 } 52 return 0; 53 } 54 LL dinic_dfs(int u,LL exp) 55 { 56 if(u==dest) return exp; 57 LL tmp; 58 for(int &i=work[u],v;i>=0;i=nxt[i]) 59 if(flow[i] && dist[v=pnt[i]]==dist[u]+1 && (tmp=dinic_dfs(v,min(exp,flow[i])))>0) 60 { 61 flow[i]-=tmp; 62 flow[i^1]+=tmp; 63 return tmp; 64 } 65 return 0; 66 } 67 LL dinic_flow(void) 68 { 69 int i; 70 LL res=0,delta; 71 while(dinic_bfs()) 72 { 73 for(i=0;i<node;i++) work[i]=head[i]; 74 while(delta=dinic_dfs(src,inf)) res+=delta; 75 } 76 return res; 77 } 78 }Flow; 79 80 int n; 81 LL B[maxn][maxn]; 82 LL C[maxn]; 83 LL BB[maxn]; 84 int main() 85 { 86 int cas; 87 scanf("%d",&cas); 88 while (cas--) 89 { 90 scanf("%d",&n); 91 int s = 0, t = n + 1; 92 93 Flow.init(n+2,s,t); 94 LL sum = 0; 95 for (int i=1;i<=n;i++) 96 { 97 BB[i] = 0; 98 for (int j=1;j<=n;j++) 99 { 100 scanf("%I64d",&B[i][j]); 101 BB[i] += B[i][j]; 102 Flow.add(i,j,B[i][j],0); 103 } 104 Flow.add(s,i,BB[i],0); 105 sum += BB[i]; 106 } 107 for (int i=1;i<=n;i++) 108 { 109 scanf("%I64d",&C[i]); 110 Flow.add(i,t, C[i],0); 111 } 112 113 // puts("dfs"); 114 LL ans = sum - Flow.dinic_flow(); 115 116 printf("%I64d\n",ans); 117 } 118 return 0; 119 }
SAP: 671MS
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 #include<vector> 6 #define LL long long 7 using namespace std; 8 9 const int maxn = 1011; 10 const int maxm = 4000010; 11 const LL inf = 9999999999; 12 13 14 15 16 struct SAP{ 17 struct Edge{ 18 int v, next; 19 LL w; 20 }edge[maxm]; 21 int head[maxn]; 22 23 int cnt; 24 int n, s, t;//n = t + 1; 25 26 27 int pre[maxn],cur[maxn],dis[maxn]; 28 LL gap[maxn]; 29 30 void add(int u,int v,LL w) 31 { 32 edge[cnt].v=v; 33 edge[cnt].w=w; 34 edge[cnt].next=head[u]; 35 head[u]=cnt++; 36 edge[cnt].v=u; 37 edge[cnt].w=0; 38 edge[cnt].next=head[v]; 39 head[v]=cnt++; 40 } 41 42 LL sap() 43 { 44 LL flow=0,aug=inf; 45 int u; 46 bool flag; 47 for(int i=0;i<=n;i++) 48 { 49 cur[i]=head[i]; 50 gap[i]=dis[i]=0; 51 } 52 gap[s]=n; 53 u=pre[s]=s; 54 while(dis[s]<n) 55 { 56 flag=0; 57 for(int &j=cur[u];j!=-1;j=edge[j].next) 58 { 59 int v=edge[j].v; 60 if(edge[j].w>0&&dis[u]==dis[v]+1) 61 { 62 flag=1; 63 if(edge[j].w<aug) aug=edge[j].w; 64 pre[v]=u; 65 u=v; 66 if(u==t) 67 { 68 flow+=aug; 69 while(u!=s) 70 { 71 u=pre[u]; 72 edge[cur[u]].w-=aug; 73 edge[cur[u]^1].w+=aug; 74 } 75 aug=inf; 76 } 77 break; 78 } 79 } 80 if(flag) 81 continue; 82 int mindis=n; 83 for(int j=head[u];j!=-1;j=edge[j].next) 84 { 85 int v=edge[j].v; 86 if(edge[j].w>0&&dis[v]<mindis) 87 { 88 mindis=dis[v]; 89 cur[u]=j; 90 } 91 } 92 if((--gap[dis[u]])==0) 93 break; 94 gap[dis[u]=mindis+1]++; 95 u=pre[u]; 96 } 97 98 return flow; 99 100 } 101 102 void init(int __n,int __s, int __t) 103 { 104 n = __n; 105 s = __s; 106 t = __t; 107 cnt = 0; 108 memset(head,-1,sizeof(head)); 109 } 110 }Flow; 111 112 int n; 113 LL B[maxn][maxn]; 114 LL C[maxn]; 115 LL BB[maxn]; 116 int main() 117 { 118 int cas; 119 scanf("%d",&cas); 120 while (cas--) 121 { 122 scanf("%d",&n); 123 int s = 0, t = n + 1; 124 125 Flow.init(n+2,s,t); 126 LL sum = 0; 127 for (int i=1;i<=n;i++) 128 { 129 BB[i] = 0; 130 for (int j=1;j<=n;j++) 131 { 132 scanf("%I64d",&B[i][j]); 133 BB[i] += B[i][j]; 134 Flow.add(j,i,B[i][j]); 135 } 136 Flow.add(i,t,BB[i]); 137 sum += BB[i]; 138 } 139 for (int i=1;i<=n;i++) 140 { 141 scanf("%I64d",&C[i]); 142 Flow.add(s,i, C[i]); 143 } 144 145 // puts("dfs"); 146 LL ans = sum - Flow.sap(); 147 148 printf("%I64d\n",ans); 149 } 150 return 0; 151 }