zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    Oracle在linux下的开机自启动(详细)转
    Xlib: connection to ":0.0" refused by server Xlib: No protocol specified解决方案
    java Comparable和Comaprator的对比
    java异常——RuntimeException和User Define Exception
    堆排序
    Java实现 蓝桥杯 算法提高 复数四则运算
    Java实现 蓝桥杯 算法训练 约数个数
    Java实现 蓝桥杯 算法训练 约数个数
    Java实现 蓝桥杯 算法提高 01背包
    Java实现 蓝桥杯 算法提高 判断名次
  • 原文地址:https://www.cnblogs.com/skylee03/p/7454993.html
Copyright © 2011-2022 走看看