码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2014-10-05 01:27:37      阅读:293      评论:0      收藏:0      [点我收藏+]

标签:blog   io   os   ar   for   sp   2014   c   on   


==线代好难


#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;
}


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

标签:blog   io   os   ar   for   sp   2014   c   on   

原文地址:http://blog.csdn.net/qq574857122/article/details/39786689

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!