HDU 4307 Matrix 最小割 矩阵乘法展开

==线代好难

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<queue>
#include<vector>
template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if(c=getchar(),c==EOF) return 0;
    while(c!='-'&&(c<'0'||c>'9')) c=getchar();
    sgn=(c=='-')?-1:1;
    ret=(c=='-')?0:(c-'0');
    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
    ret*=sgn;
    return 1;
}
template <class T>
inline void pt(T x) {
    if (x <0) {
        putchar('-');
        x = -x;
    }
    if(x>9) pt(x/10);
    putchar(x%10+'0');
}
typedef int ll;
const int N = 1005;
const int M = N*N + 2*N;
const int inf = 107374182;
const long long inf64 = 1e18;

using namespace std;

struct Edge{
    int from, to;
	ll cap; int nex;
}edge[M*2];//注意这个一定要够大 不然会re 还有反向弧

int head[N], edgenum;
void add(int u, int v, ll cap, ll rw = 0){ //如果是有向边则:add(u,v,cap); 如果是无向边则:add(u,v,cap,cap);
    Edge E = { u, v, cap, head[u]};
    edge[ edgenum ] = E;
    head[u] = edgenum ++;

    Edge E2= { v, u, rw,  head[v]};
    edge[ edgenum ] = E2;
    head[v] = edgenum ++;
}
int sign[N];
bool BFS(int from, int to){
    memset(sign, -1, sizeof(sign));
    sign[from] = 0;

    queue<int>q;
    q.push(from);
    while( !q.empty() ){
        int u = q.front(); q.pop();
        for(int i = head[u]; i!=-1; i = edge[i].nex)
        {
            int v = edge[i].to;
            if(sign[v]==-1 && edge[i].cap)
            {
                sign[v] = sign[u] + 1, q.push(v);
                if(sign[to] != -1)return true;
            }
        }
    }
    return false;
}
int Stack[N], top, cur[N];
ll Dinic(int from, int to){
    ll ans = 0;
    while( BFS(from, to) )
    {
        memcpy(cur, head, sizeof(head));
        int u = from;      top = 0;
        while(1)
        {
            if(u == to)
            {
                ll flow = inf, loc;//loc 表示 Stack 中 cap 最小的边
                for(int i = 0; i < top; i++)
                    if(flow > edge[ Stack[i] ].cap)
                    {
                        flow = edge[Stack[i]].cap;
                        loc = i;
                    }

                    for(int i = 0; i < top; i++)
                    {
                        edge[ Stack[i] ].cap -= flow;
                        edge[Stack[i]^1].cap += flow;
                    }
                    ans += flow;
                    top = loc;
                    u = edge[Stack[top]].from;
            }
            for(int i = cur[u]; i!=-1; cur[u] = i = edge[i].nex)//cur[u] 表示u所在能增广的边的下标
                if(edge[i].cap && (sign[u] + 1 == sign[ edge[i].to ]))break;
            if(cur[u] != -1)
            {
                Stack[top++] = cur[u];
                u = edge[ cur[u] ].to;
            }
            else
            {
                if( top == 0 )break;
                sign[u] = -1;
                u = edge[ Stack[--top] ].from;
            }
        }
    }
    return ans;
}
void init(){memset(head,-1,sizeof head);edgenum = 0;}

int n;
ll b[1010][1010], c[1010], B[1010];

ll solve(){
	init();
	int from = 0, to = n +1;
	ll ans = 0;
	for(int i = 1; i <= n; i++) ans += B[i];
	for(int i = 1; i <= n; i++) {
		add(from, i, B[i]);
		add(i, to, c[i]);
	}
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= n; j++)
			if(i != j)
				add(i, j, b[i][j]);
	return ans - Dinic(from, to);
}
void input(){
    rd(n);
	memset(B, 0, sizeof B);
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= n; j++)
			rd(b[i][j]), B[i] += b[i][j];
	for(int i = 1; i <= n; i++)
		rd(c[i]);
}
int main() {
    int T; rd(T);
	while(T--) {
        input();
		pt( solve() ); putchar('\n');
	}
	return 0;
}
时间: 2024-08-02 00:10:24

HDU 4307 Matrix 最小割 矩阵乘法展开的相关文章

hdu 4920 Matrix multiplication(矩阵乘法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4920 Matrix multiplication Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 989    Accepted Submission(s): 396 Problem Description Given two matr

2014多校第五场1010 || HDU 4920 Matrix multiplication(矩阵乘法优化)

题目链接 题意 : 给你两个n*n的矩阵,然后两个相乘得出结果是多少. 思路 :一开始因为知道会超时所以没敢用最普通的方法做,所以一直在想要怎么处理,没想到鹏哥告诉我们后台数据是随机跑的,所以极端数据是不可能会有的,而我们一开始一直在想极端数据能接受的方法......后来看了鹏哥的做法,就是把是0的地方都跳过就可以了,用矩阵保存前一个非0数的位置是多少.二师兄给我看了一个代码,人家根本没用别的优化,直接将最里层k的循环提到了最外层,然后就AC了,对此我表示无语. 1 #include <cstd

hdu 4920 Matrix multiplication (矩阵乘法)

Problem Description Given two matrices A and B of size n×n, find the product of them.bobo hates big integers. So you are only asked to find the result modulo 3. Input The input consists of several tests. For each tests:The first line contains n (1≤n≤

hdu 4920 Matrix multiplication(矩阵相乘)多校训练第5场

Matrix multiplication                                                                           Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description Given two matrices A and B of size n×n, find the

HDU 4914 Linear recursive sequence(矩阵乘法递推的优化)

题解见X姐的论文 矩阵乘法递推的优化,只是mark一下.. HDU 4914 Linear recursive sequence(矩阵乘法递推的优化)

HDU 2865 Birthday Toy [Polya 矩阵乘法]

传送门 题意: 相邻珠子不能相同,旋转等价.$n$个珠子$k$中颜色,求方案数 首先中间珠子$k$种选择,$k--$如果没有相邻不同的限制,就和$POJ\ 2154$一样了$|C(f)|=k^{\#(f)}$但是有了相邻不同的限制,每种循环的颜色就不能任意选择了旋转等价循环个数是$gcd(n,i)$,同一个循环的元素相差$i$步容易得到只要满足长度$gcd(n,i)$的一段相邻颜色不同整个环就不同了,因为这样的一段正好每个循环有一个元素考虑$DP$,$f[i]$表示$i$个元素组成的环染色方案数

HDU 4859 海岸线 最小割

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4859 题解: 这题考察的是最小割. 我们可以这样想:海岸线的长短变化都是E引起的,我们通过把’E'变成'.'或'D'来使海岸线最大化. 我们要算海岸线就是算格子‘.'和格子'D'(在原有地图周围四面都要加’D‘)相邻的面数,要使它最大,就是要使'.'与’.':'D'与'D'相邻的面数最小,而面数最小可以用最小割来做. 现在我们先把格子上的点黑白染色,(i+j)%2==1的为A类,为0的为B类, 在

HDU 3061 Battle(最小割----最大权闭合图)

题目地址:HDU 3061 多校中遇到的最小割的最大权闭合模型花了一上午时间终于看懂啦. 最大权闭合图就是将一些互相有依赖关系的点转换成图,闭合图指的是在图中的每一个点的后继点都是在图内的. 还要明白简单割的概念,就是指所有的割边都与源点或汇点相连.然后让源点与正权点相连,汇点与负权点相连,权值均为其绝对值,有依赖关系的点连一条有向边,如果a必须在b的基础上,那么就连一条a->b的有向边,权值为INF.最后用所有正权值得和减去最小割的值就是答案. 具体证明可看胡伯涛大牛的国家队集训论文<最小割

HDU 3046【最小割】

题目大意:在一个n*m的矩阵上,1代表羊,2代表狼,0代表平地,我们有长度为1的一个栅栏(不是放在格子上的,是放在格子和格子之间的空隙上的),问使用最少的栅栏,能够使得狼吃不到羊. 又学到了一招,以前一直以为建图是要先设好S点T点,在把其他的点和他们两一一相连.今天学到了原来可以在整个map上根据条件建好图,再把其中的某些目标点和源汇点相连的. 思路如下: 1.建立最小割模型: ①建立源点S,将源点S连入各个有狼的节点上,权值设定为INF,表示狼可以从任意方向出发. ②建立汇点T,将各个羊节点连