[TJOI2015]线性代数

OJ题号:
BZOJ3996

题目大意:
  给定一个矩阵$B_{nn}$,矩阵$C_{1n}$,存在一个01矩阵$A_{1,n}$使得$d=(A imes B-c) imes A^mathsf{T}$最大,求$d$的最大值。

思路:
  化简以后可以得到$d=displaystyle{sum_{i=1}^{n}sum_{j=1}^{n}}a_ia_jb_{ij}-displaystyle{sum_{i=1}^{n}}a_ic_i$。
  由于$A$是一个01矩阵,因此我们可以将这题转化为“取物品”的问题。
  已知有$n$个物品,取第$i$个有$c_i$的收益,若同时取$i$和$j$则有$c_i+c_j+b_{ij}$的收益,求最大收益。
  我们先设置超级源汇$S$和$T$,然后对于所有的$(i,j)$,连一条从$S$到$(i,j)$的容量为$b_{ij}$的边,再分别连从$(i,j)$到$i$和$j$的容量为$infty$的边。
  对于每一个$i$,连一条从$i$到$T$的容量为$c_i$的边。
  然后求出最小割$f$,则$d=displaystyle{sum_{i=1}^nsum_{j=1}^n}b_{ij}-f$。
  然后用Edmonds-Karp算法写了一遍发现TLE了,改成用Dinic加上当前弧优化就能AC了。

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<vector>
 5 #include<cstring>
 6 inline int getint() {
 7     char ch;
 8     while(!isdigit(ch=getchar()));
 9     int x=ch^'0';
10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
11     return x;
12 }
13 const int inf=0x7fffffff;
14 const int E=1501000,V=250502;
15 int s,t;
16 struct Edge {
17     int from,to,remain;
18 };
19 int sz=0;
20 Edge e[E];
21 std::vector<int> g[V];
22 inline void add_edge(const int u,const int v,const int w) {
23     e[sz]=(Edge){u,v,w};
24     g[u].push_back(sz);
25     sz++;
26 }
27 int lev[V];
28 inline void bfs() {
29     for(int i=1;i<=t;i++) lev[i]=inf;
30     lev[s]=0;
31     std::queue<int> q;
32     q.push(s);
33     while(!q.empty()) {
34         int x=q.front();
35         q.pop();
36         for(unsigned i=0;i<g[x].size();i++) {
37             Edge &y=e[g[x][i]];
38             if(y.remain&&lev[y.to]==inf) {
39                 lev[y.to]=lev[x]+1;
40                 q.push(y.to);
41             }
42         }
43     }
44 }
45 unsigned cur[V]={0};
46 int dfs(const int x,const int flow) {
47     if(x==t) return flow;
48     for(unsigned &i=cur[x];i<g[x].size();i++) {
49         Edge y=e[g[x][i]];
50         if(y.remain&&lev[x]<lev[y.to]) {
51             int f=dfs(y.to,std::min(flow,y.remain));
52             if(f) {
53                 e[g[x][i]].remain-=f;
54                 e[g[x][i]^1].remain+=f;
55                 return f;
56             }
57         }
58     }
59     return 0;
60 }
61 inline int Dinic() {
62     int maxflow=0;
63     for(;;) {
64         bfs();
65         if(lev[t]==inf) break;
66         while(int flow=dfs(s,inf)) {
67             maxflow+=flow;
68         }
69     }
70     return maxflow;
71 }
72 int main() {
73     int n=getint();
74     s=0,t=n*(n+1)+1;
75     int ans=0;
76     for(int i=1;i<=n;i++) {
77         for(int j=1;j<=n;j++) {
78             int id=i*n+j;
79             int w=getint();
80             ans+=w;
81             add_edge(s,id,w);
82             add_edge(id,s,0);
83             add_edge(id,i,inf);
84             add_edge(i,id,0);
85             add_edge(id,j,inf);
86             add_edge(j,id,0);
87         }
88     }
89     for(int i=1;i<=n;i++) {
90         add_edge(i,t,getint());
91         add_edge(t,i,0);
92     }
93     printf("%d
",ans-Dinic());
94     return 0;
95 }

Edmonds-Karp的TLE代码:

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<vector>
 5 #include<cstring>
 6 inline int getint() {
 7     char ch;
 8     while(!isdigit(ch=getchar()));
 9     int x=ch^'0';
10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
11     return x;
12 }
13 const int inf=0x7fffffff;
14 const int E=1501000,V=250502;
15 int s,t;
16 struct Edge {
17     int from,to,remain;
18 };
19 int sz=0;
20 Edge e[E];
21 std::vector<int> g[V];
22 inline void add_edge(const int u,const int v,const int w) {
23     e[sz]=(Edge){u,v,w};
24     g[u].push_back(sz);
25     sz++;
26 }
27 int a[V],p[V];
28 inline int Augment() {
29     memset(a,0,sizeof a);
30     a[s]=inf;
31     std::queue<int> q;
32     q.push(s);
33     while(!q.empty()) {
34         int x=q.front();
35         q.pop();
36         for(unsigned i=0;i<g[x].size();i++) {
37             Edge &y=e[g[x][i]];
38             if(y.remain&&!a[y.to]) {
39                 a[y.to]=std::min(a[x],y.remain);
40                 p[y.to]=g[x][i];
41                 q.push(y.to);
42             }
43         }
44         if(a[t]) break;
45     }
46     return a[t];
47 }
48 inline int EdmondsKarp() {
49     int maxflow=0;
50     while(int flow=Augment()) {
51         for(int i=t;i!=s;i=e[p[i]].from) {
52             e[p[i]].remain-=flow;
53             e[p[i]^1].remain+=flow;
54         }
55         maxflow+=flow;
56     }
57     return maxflow;
58 }
59 int main() {
60     int n=getint();
61     s=0,t=n*(n+1)+1;
62     int ans=0;
63     for(int i=1;i<=n;i++) {
64         for(int j=1;j<=n;j++) {
65             int id=i*n+j;
66             int w=getint();
67             ans+=w;
68             add_edge(s,id,w);
69             add_edge(id,s,0);
70             add_edge(id,i,inf);
71             add_edge(i,id,0);
72             add_edge(id,j,inf);
73             add_edge(j,id,0);
74         }
75     }
76     for(int i=1;i<=n;i++) {
77         add_edge(i,t,getint());
78         add_edge(t,i,0);
79     }
80     printf("%d
",ans-EdmondsKarp());
81     return 0;
82 }
View Code
原文地址:https://www.cnblogs.com/skylee03/p/7454993.html