题目给了一个满足最大流的残量网络,判断是否费用最小。

如果残量网络中存在费用负圈,那么不是最优,在这个圈上增广,增广1的流量就行了。

1.SPFA中某个点入队超过n次,说明存在负环,但是这个点不一定在负环上。

2.这个负环可能包括汇点t,所以构建残量网络的时候也要考虑防空洞到t上的容量。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<sstream>
#include<cmath>
#include<climits>
#include<string>
#include<map>
#include<queue>
#include<vector>
#include<stack>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define pb(a) push(a)
#define INF 0x1f1f1f1f
#define lson idx<<1,l,mid
#define rson idx<<1|1,mid+1,r
#define PI 3.1415926535898
template<class T> T min(const T& a,const T& b,const T& c) {
return min(min(a,b),min(a,c));
}
template<class T> T max(const T& a,const T& b,const T& c) {
return max(max(a,b),max(a,c));
}
void debug() {
#ifdef ONLINE_JUDGE
#else freopen("in.txt","r",stdin);
// freopen("d:\\out1.txt","w",stdout);
#endif
}
int getch() {
int ch;
while((ch=getchar())!=EOF) {
if(ch!=' '&&ch!='\n')return ch;
}
return EOF;
} const int maxn = ;
int X[maxn], Y[maxn], B[maxn];
int P[maxn], Q[maxn], C[maxn];
int E[maxn][maxn];
int N, M; bool input()
{
if(scanf("%d%d", &N, &M) == EOF) return false;
for(int i = ; i <= N; i++)
scanf("%d%d%d", &X[i], &Y[i], &B[i]);
for(int i = ; i <= M; i++)
scanf("%d%d%d", &P[i], &Q[i], &C[i]);
for(int i = ; i <= N; i++)
for(int j = ; j <= M; j++)
scanf("%d", &E[i][j]);
return true;
} struct Edge
{
int from, to, cost, cap;
};
const int maxv = maxn * ;
int n,s,t;
vector<int> g[maxv];
vector<Edge> edge;
int road[maxv];
int d[maxv];
int inq[maxv];
int vcnt[maxv]; int SPFA()
{
queue<int> q;
memset(d, INF, sizeof(d));
memset(inq, false, sizeof(inq));
memset(vcnt, , sizeof(vcnt));
d[s] = ;
road[s] = -;
q.push(s); while(!q.empty())
{
int u = q.front(); q.pop();
inq[u] = false;
for(int i = ; i < g[u].size(); i++)
{
Edge &e = edge[g[u][i]];
if(e.cap > && d[e.to] > d[u] + e.cost)
{
d[e.to] = d[u] + e.cost;
road[e.to] = g[u][i];
if(!inq[e.to])
{
inq[e.to] = true;
if(++vcnt[e.to] > n) return e.to;
q.push(e.to);
}
}
}
}
return -;
}
void add(int from, int to, int cost, int cap, int flow)
{
edge.push_back((Edge){from, to, cost, cap - flow});
g[from].push_back(edge.size() - );
edge.push_back((Edge){to, from, -cost, flow});
g[to].push_back(edge.size() - );
} int Cost(int i, int j)
{
return abs(X[i] - P[j]) + abs(Y[i] - Q[j]) + ;
} void init()
{
for(int i = ; i <= n; i++)
g[i].clear();
edge.clear();
}
void construct()
{
n = N + M + ;
s = n - ;
t = n;
init(); int sum[maxn] = {};
for(int i = ; i <= N; i++)
for(int j = ; j <= M; j++)
sum[j] += E[i][j];
for(int i = ; i <= N; i++)
add(s, i, , B[i], );
for(int j = ; j <= M; j++)
add(j + N, t, , C[j], sum[j]);
for(int i = ; i <= N; i++)
for(int j = ; j <= M; j++)
add(i, j + N, Cost(i, j), min(B[i], C[i]), E[i][j]);
} int vis[maxv];
void solve()
{
int u = SPFA();
if(u == -)
{
printf("OPTIMAL\n");
return ;
} memset(vis, , sizeof(vis));
while()
{
if(vis[u]) break;
vis[u] = true;
u = edge[road[u]].from;
} memset(vis, , sizeof(vis));
for(int e = road[u]; !vis[edge[e].to]; e = road[edge[e].from])
{
int x = edge[e].from;
int y = edge[e].to;
vis[y] = true;
if(x == t || y == t) continue;
if(x < y) E[x][y - N] += ;
else E[y][x - N] -= ;
} printf("SUBOPTIMAL\n");
for(int i = ; i <= N; i++)
for(int j = ; j <= M; j++)
printf("%d%c", E[i][j], j == M? '\n': ' ');
}
int main()
{
debug();
while(input())
{
construct();
solve();
}
return ;
}

最新文章

  1. mysql索引失效
  2. Asp.net+JS 分页
  3. Mongodb的Samus驱动
  4. 手机端的click
  5. html5的结构标记与内联元素
  6. OAF_EO系列5 - Update详解和实现(案例)
  7. ASP.NET MVC 学习第一天
  8. NOIP2011 计算系数
  9. 各种OS间文件传输
  10. 服务器监控之 ping 监控
  11. [ExtJS5学习笔记]第十五节 Extjs5表格显示不友好?panel的frame属性在作怪
  12. 第二次作业——个人项目实战(Sudoku)
  13. MYSQL问题解决方案:Access denied for user &#39;root&#39;@&#39;localhost&#39; (using password:YES)
  14. 滴滴 App 的质量优化框架 Booster,开源了!
  15. Serialization
  16. .NetCore WebApi 添加 Log4Net
  17. MTK 自定义按键添加广播
  18. 【转载】VS配置路径和宏
  19. 使用ScriptEngineManager解析json
  20. 在Ubuntu中开启Soft AP功能

热门文章

  1. duplicate symbols for architecture armv7解决办法
  2. 快速求n的质因子(数论)
  3. 安装ss
  4. sql语句,怎么查看一个表中的所有约束
  5. 001_JavaScript 错误 - Throw、Try 和 Catch
  6. Oracle时间戳 与时间之间的相互转换
  7. Sqoop2入门之导入关系型数据库数据到HDFS上(sqoop2-1.99.4版本)
  8. FW: javascripts 要不要加引号
  9. 解决【win10管理员已阻止程序运行】问题时有感
  10. 简单实用的Windows命令(二)