程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> HDU 4307 Matrix 最小割 矩陣乘法展開

HDU 4307 Matrix 最小割 矩陣乘法展開

編輯:C++入門知識

HDU 4307 Matrix 最小割 矩陣乘法展開



==線代好難


#include
#include
#include
#include
#include
#include
#include
template   
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   
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;

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


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved