bzoj3996 dinic

来源:互联网 发布:澳洲留学生知乎 编辑:程序博客网 时间:2024/06/06 18:13

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3996

A^T为A的转置(一开始没懂什么意思,后面才知道其实就是把矩阵沿对角线翻转,即B[i][j]=A[j][i])
然后用矩阵推一下就是一个网络流的代价和收益(同时选取2个)问题。

#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define INF 100000000struct sef { int ne,en,w; }h[3500050];int tot,first[500005],cur[500050];int q[3500050],tail;int dis[500050];int n,T,ans,nn;inline void setl(int x,int y,int v){    h[++tot]=(sef){first[x],y,v};    first[x]=tot;    h[++tot]=(sef){first[y],x,0};    first[y]=tot;}inline bool Bfs(){    q[tail=1]=0;    for (int i=1;i<=T;++i) dis[i]=-1;    dis[0]=0;    int x,y;    for (int j=1;j<=tail;++j) {        x=q[j]; cur[x]=first[x];        for (int i=first[x];y=h[i].en,i;i=h[i].ne)            if (h[i].w&&dis[y]==-1)                 dis[y]=dis[x]+1,q[++tail]=y;    }    return (dis[T]>-1);}int Dfs(int x,int flow){    if (x==T) return flow;    int y,tmp=0,ret;    for (int &i=cur[x];y=h[i].en,i;i=h[i].ne)        if (dis[y]==dis[x]+1) {            ret=Dfs(y,min(flow,h[i].w));            h[i].w-=ret;    h[i^1].w+=ret;            flow-=ret;  tmp+=ret;            if (!flow) return tmp;        }    return tmp;}int main(){    scanf("%d",&n); nn=n*n; tot=1;    int x,p;    for (int i=1;i<=n;++i) {        p=(i-1)*n;        for (int j=1;j<=n;++j) {            scanf("%d",&x);            ans+=x;            setl(0,p+j,x);            setl(p+j,nn+i,INF);            setl(p+j,nn+j,INF);        }    }    T=nn+n+1;    for (int i=1;i<=n;++i) {        scanf("%d",&x);        setl(nn+i,T,x);    }    while (Bfs()) ans-=Dfs(0,INF);    printf("%d\n",ans);}
1 0
原创粉丝点击