【bzoj3996】[TJOI2015]线性代数

来源:互联网 发布:plc网络通信 编辑:程序博客网 时间:2024/06/05 04:33

首先转化题目:
给你n个物品,可以选或不选。
选第i个物品需要c[i]的代价。
同时选第i和第j个物品获得b[i][j]的收益
问最大收益。
网络流建图:
考虑sum=ni=1nj=1b[i][j]
剩下就变成了算代价最小(也就是最小割)
建点(i,j)i,对于每个点(i,j),向i,j连一条容量为inf的边。
S向每个点(i,j)连一条容量为b[i][j]的边
每个点iT连一条容量为c[i]的边。
然后跑最大流就好。

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define N 509#define inf 0x3f3f3f3fusing namespace std;int n,b[N][N],c[N],sum;int number=1,pos,cur[N*N],dis[N*N];bool vis[N*N];vector<int> G[N*N];struct edge{    int from,to,flow,cap;    int rest()    {        return cap-flow;    }    void add(int x,int y,int z)    {        from=x,to=y,cap=z,flow=0;    }}e[N*N<<3];void add(int x,int y,int z){    e[++number].add(x,y,z);    G[x].push_back(number);    e[++number].add(y,x,0);    G[y].push_back(number);}#define E e[G[x][i]]bool bfs(int s,int t){    memset(vis,0,sizeof(vis));    queue<int> Q;    Q.push(s);    dis[s]=0;    vis[s]=1;    while (!Q.empty())    {        int x=Q.front();        Q.pop();        for (int i=0;i<(int)G[x].size();i++)            if (!vis[E.to]&&E.rest()>0)            {                vis[E.to]=1;                dis[E.to]=dis[x]+1;                Q.push(E.to);            }    }    return vis[t];}int dfs(int x,int a,int t){    if (x==t||a==0) return a;    int flow=0,f;    for (int &i=cur[x];i<(int)G[x].size();i++)        if (dis[x]+1==dis[E.to]&&(f=dfs(E.to,min(a,E.rest()),t))>0)        {            E.flow+=f;            e[G[x][i]^1].flow-=f;            flow+=f;            a-=f;            if (!a) break;        }    return flow;}int Maxflow(int s,int t){    int flow=0;    while (bfs(s,t))    {        memset(cur,0,sizeof(cur));        flow+=dfs(s,inf,t);    }    return flow;}#undef Eint read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return s*x;}int main(){    n=read();    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)        {            b[i][j]=read(),sum+=b[i][j];            add(0,(i-1)*n+j,b[i][j]);            add((i-1)*n+j,n*n+i,inf);            add((i-1)*n+j,n*n+j,inf);        }    for (int i=1;i<=n;i++)    {        c[i]=read();        add(n*n+i,n*n+n+1,c[i]);    }    printf("%d\n",sum-Maxflow(0,n*n+n+1));    return 0;}
原创粉丝点击