您的位置:首页 > 理论基础 > 计算机网络

【网络流24题16】数字梯形问题

2018-02-03 20:45 381 查看

题面传送机

Little Knowledge

求最大果断最大费用流

最大费用流就只是在最小费用流的基础上把价值都取相反数

Sol

这道题是由三道小题组成的(长沙中考数学第24题的感觉=m=)

那我们就以解数学题的步骤写

首先列出条件(读入)

然后逐小题分析 , 分为下代码的solve1 solve2 solve3

然后就做辅助线了(建图)

分三种:

①solve1:

(i) 建立超源(S)汇(E)点

(ii) 为了保证不相交 把每个点拆成两个 并连有向边 i.a -> i.b 流量为1 费用为i的值

(iii) S与梯形的顶部m个点连有向边 S -> i.a 流量为1 费用为0(因为要从每一个顶边点出发)

(iiii) 底部点与E连有向边 i.b -> E 流量为 1 费用为 0

(iiiii) 每个点和其能到的点连有向边 流量为 1 费用为 0

②solve2:

(i) 建立超源(S)汇(E)点

(ii) 因为可以点相交 不拆点了

(iii) S与顶部m个节点连有向边 流量为 1 费用为 0

(iiii) 底部点与E相连 流量为 INF 费用为 底部点值

(iiii) 每个点和其能到的点连有向边 流量为 1 费用为 这个点的值

③solve3:

(i) 建立超源(S)汇(E)点

(ii) 这次修改建立在solve2上

(iii) 将除了连起点的边(因为要从每个起点引出一条线)的容量都改成INF就可以完美解决边相交了

Code

#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstring>
#define inc(i) (i = -(~i))
#define dec(i) (i = ~(-i))
using namespace std;

namespace fast
{
inline char Getchar()
{
static char buf[100001] , *p1 = buf , *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf , 1 , 100000 , stdin) , p1 == p2) ? EOF : *p1 ++;
}
inline int read()
{
int num = 0; char c = 0;
while(!isdigit(c)) c = Getchar();
while(isdigit(c)) num = num * 10 + c - '0' , c = Getchar();
return num;
}
}
using namespace fast;

const int M = 30000 + 7 , N = 500 + 7 , INF = 1e9 + 7;
int n , m , Value
, S , E , Order[30][30] , Total , Cost , Dep
, k;
int Head
, Node[M] , W[M] , Co[M] , tot = 1 , Next[M];

inline void Add(int u , int v , int w , int c)
{
Next[inc(tot)] = Head[u] , Head[u] = tot , W[tot] = w , Co[tot] = -c , Node[tot] = v;
Next[inc(tot)] = Head[v] , Head[v] = tot , W[tot] = 0 , Co[tot] = c , Node[tot] = u;
}

inline void in()
{
m = read() , n = read();
for(int i = 1 ; i <= n ; inc(i))
{
for(int j = 1 ; j <= m + i - 1 ; inc(j))
inc(Total) , Value[Total] = read() , Order[i][j] = Total;
}
S = (Total << 1) + 1 , E = S + 1;
}

inline void Build1()
{
for(int i = 1 ; i <= Total ; inc(i))
Add(i , i + Total , 1 , Value[i]);
for(int i = 1 ; i <= m ; inc(i))
Add(S , Order[1][i] , 1 , 0);
for(int i = 1 ; i <= m + n - 1 ; inc(i))
Add(Order
[i] + Total , E , 1 , 0);
for(int i = 1 ; i < n ; inc(i))
for(int j = 1 ; j <= m + i - 1 ; inc(j))
{
Add(Order[i][j] + Total , Order[i + 1][j] , 1 , 0);
Add(Order[i][j] + Total , Order[i + 1][j + 1] , 1 , 0);
}
}

inline void Build2()
{
for(int i = 1 ; i <= m ; inc(i))
Add(S , Order[1][i] , 1 , 0);
for(int i = 1 ; i <= m + n + 1 ; inc(i))
Add(Order
[i] , E , INF , Value[Order
[i]]);
for(int i = 1 ; i <= n ; inc(i))
for(int j = 1 ; j <= m + i - 1 ; inc(j))
{
Add(Order[i][j] , Order[i + 1][j] , 1 , Value[Order[i][j]]);
Add(Order[i][j] , Order[i + 1][j + 1] , 1 , Value[Order[i][j]]);
}
}

inline void Build3()
{
for(int i = 1 ; i <= m ; inc(i))
Add(S , Order[1][i] , 1 , 0);
for(int i = 1 ; i <= m + n - 1 ; inc(i))
Add(Order
[i] , E , INF , Value[Order
[i]]);
for(int i = 1 ; i < n ; inc(i))
for(int j = 1 ; j <= m + i - 1 ; inc(j))
{
Add(Order[i][j] , Order[i + 1][j] , INF , Value[Order[i][j]]);
Add(Order[i][j] , Order[i + 1][j + 1] , INF , Value[Order[i][j]]);
}
}

struct Queue
{
int Que[N * 10] , l , r;
inline void cls() {l = 100 , r = 99;}
inline int top() {return Que[l];}
inline void push(int x) {Que[inc(r)] = x;}
inline bool full() {return r >= l;}
inline void pop() {inc(l);}
}Q;
bool inq
, book
;

inline bool SPFA()
{
memset(inq , 0 , sizeof(inq));
memset(Dep , 127 , sizeof(Dep));
int Big = Dep[E];
Dep[E] = 0; Q.cls() , Q.push(E);
int u , v;
while(Q.full())
{
u = Q.top(); Q.pop();
for(int i = Head[u] ; i ; i = Next[i])
{
v = Node[i];
if(W[i ^ 1] && Dep[v] > Dep[u] - Co[i])
{
Dep[v] = Dep[u] - Co[i];
if(!inq[v])
{
inq[v] = 1;
Q.push(v);
}
}
inq[u] = 0;
}
}
return Dep[S] < Big;
}

inline int DFS(int u , int lastc)
{
if(u == E) return lastc;
int Now = 0 , Flow , v;
book[u] = 1;
for(int i = Head[u] ; i ; i = Next[i])
{
int v = Node[i];
if(!book[v] && W[i] && Dep[u] - Co[i] == Dep[v])
{
Flow = DFS(v , min(lastc - Now , W[i]));
if(Flow)
{
W[i] -= Flow;
W[i ^ 1] += Flow;
Now += Flow;
Cost += Flow * Co[i];
if(Now == lastc)    break;
}
}
}
return Now;
}

inline void Max_Flow()
{
int Ans = 0 , Flow;
while(SPFA())
{
if(!DFS(S , INF + 1)) break;
memset(book , 0 , sizeof(book));
}
}

inline void Clear()
{
tot = 1 , Cost = 0;
memset(Head , 0 , sizeof(Head));
}

int main()
{
in();

Build1();
Max_Flow();
printf("%d\n" , -Cost);

Clear();
Build2();
Max_Flow();
printf("%d\n" , -Cost);

Clear();
Build3();
Max_Flow();
printf("%d" , -Cost);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: