[TJOI 2015] 线性代数

Posted functionendless

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[TJOI 2015] 线性代数相关的知识,希望对你有一定的参考价值。

题目传送-Luogu3973

题意:

给定一个(n×n)的矩阵(B)和一个(1×n)的矩阵(C),求一个(1×n)(01)矩阵(A)。使得(D=(A×B-C)×A^{sf T})最大,其中(A^{sf T})(A)的转置。输出(D)
(n le 500,1 le Allelement le 1000)

题解:

emmm这是道网络流..二十多万条边跑网络流也是有信仰的了
脑补一下我们可以发现以下性质:
只有当(a_i=1)(a_j=1)时,(B_{i,j})才能被算贡献
也就意味着必须要选上(c_i)(c_j)的代价才能有(B_{i,j})的贡献
这东西就和这题等价啦link

过程:

我:500*500=25000

代码:

const int N=510,M=250010;
int n,m;
int p[N];
struct PEO {
    int a,b,v;
    inline void in() {
        read(a); read(b); read(v);
    }
}a[M];
namespace FLOW {
    const int ALL=N+M,EDGE=(N+M*3)<<1;
    int S,T;
    int head[ALL],nxt[EDGE],to[EDGE],cap[EDGE],lst=1;
    inline void adde(int x,int y,int c) {
        nxt[++lst]=head[x]; to[lst]=y; cap[lst]=c; head[x]=lst;
    }
    inline void con(int x,int y,int c) {
        adde(x,y,c); adde(y,x,0);
    }
    int stp[ALL];
    inline bool bfs(int S) {
        queue<int> que; mem(stp,63);
        que.push(S); stp[S]=0; 
        while(!que.empty()) {
            int u=que.front(); que.pop();
            for(int i=head[u];i;i=nxt[i]) {
                int v=to[i];
                if(cap[i] && stp[v]>stp[u]+1) {
                    stp[v]=stp[u]+1;
                    que.push(v);
                }
            }
        }
        return stp[T]!=stp[0];
    }
    int cur[ALL];
    inline int dfs(int u,int f) {
        if(!f || u==T) return f;
        for(int &i=cur[u];i;i=nxt[i]) {
            int v=to[i];
            if(stp[v]==stp[u]+1 && cap[i]) {
                int flow=dfs(v,min(f,cap[i]));
                if(flow) {
                    cap[i]-=flow; cap[i^1]+=flow;
                    return flow;
                }
            }
        }
        return 0;
    }
    inline int Dinic() {
        int Flow=0,add=0;
        while(bfs(S)) {

            memcpy(cur,head,sizeof(head));
            do {add=dfs(S,INF); Flow+=add;} while(add);
        }
        return Flow;
    }
    inline void Construct() {
        S=n+m+1; T=S+1;
        for(int i=1;i<=n;i++) {
            con(S,i,p[i]);
        }
        for(int i=1;i<=m;i++) {
            con(a[i].a,i+n,INF);
            con(a[i].b,i+n,INF);
            con(i+n,T,a[i].v);
        }
    }
    inline int main() {
        Construct();
        // printf("%lld %lld %lld %lld
",S,T,lst,EDGE);
        return Dinic();
    }
}
int sum=0;
signed main() {
    read(n); m=n*n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++) {
            int p=(i-1)*n+j;
            a[p].a=i; a[p].b=j; read(a[p].v);
            sum+=a[p].v;
        }
    for(int i=1;i<=n;i++) read(p[i]);
    int ans=FLOW::main();
    printf("%d
",sum-ans);
    return 0;
}

用时:5min(用模板)






以上是关于[TJOI 2015] 线性代数的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3996: [TJOI2015]线性代数

[TJOI2015]线性代数(网络流)

[TJOI 2015] 线性代数

bzoj3996:[TJOI2015]线性代数

BZOJ3996 TJOI2015线性代数

bzoj3996 [TJOI2015]线性代数