【问题】
近来发现了一个古老的地下迷宫,已探明该迷宫是一个A行B列的矩阵,该迷宫有N个不同的出口与N个不同的入口,任一单元格不会既为入口又为出口。为了进一步探明与发掘该迷宫,N个考古队员分别从地上的N个不同的入口进入迷宫,并且计划从N个不同的出口出来。每个队员任意选择一个出口出来,但任意两名队员不会选择同一个出口。
迷宫中的每一格与其相邻的某些格相通。该迷宫设计非常精妙,在不知道具体机关的情况下,人一旦离开其所在格后,该格将迅速关闭,且再也不能开启,也就是说每一格仅能进入一次。更糟的是,迷宫中的每一格都有一定的危险性,专家们用1至100的整数表示,数值越大表示越危险。正因为如此,再加之每一格都不很宽敞,两人一起进入比较危险,所以规定不能两个人同时进入同一格。
为了队员们的安全着想,希望你能够编程求出如何使队员们所经过单元格的危险性总和最小。
入口有两个:(1,1)即第一行第一列,(1,2)即第一行第二列
出口也有两个:(2,3)即第二行第三列,(3,4)即第三行第四列
两名队员的最好的行动方案之一,如上图红蓝箭头所示。危险程度之和最小为235。
【输入描述】
第一行是两个整数A与B(1≤A,B≤10),中间用空格分隔,表示该迷宫是A行B列的。第2行至第A+1行,每行有B个1至100以内的整数,表示该迷宫每一格的危险程度。
以下一行是一个整数K。接着K行每行有四个整数X0,Y0,X1,Y1,(1 ≤X0,X1≤A, 1≤Y0,Y1≤B) ,表示(X0,Y0),(X1,Y1)为相邻的两格,这两格互相相通。
接着一行是一个整数N(0≤N≤A*B/2),表示有N个出口与入口,保证出入口不会重合。
以下N行,每行有两个整数X0,Y0,表示每个入口的行列位置。
以下还有N行,每行有两个整数X1,Y1,表示每个出口的行列位置。
【输出描述】
输出仅一个数,若队员们不能全部到达指定目标位置,则输出-1;否则输出所有队员所经过的所有单元格的危险程度之和。
【输入样例】
3 420 30 40 3030 60 20 2020 15 20 20131 1 2 11 2 1 31 2 2 21 3 1 41 4 2 4
2 1 2 22 1 3 12 2 2 32 3 2 42 4 3 43 1 3 23 2 3 33 3 3 421 11 22 33 4
【输出样例】
之前查错是对着小明的代码查错的…………嗯…………也贴上来吧免得以后找不到了…………其实还是想说java风看着好肉疼…………
近来发现了一个古老的地下迷宫,已探明该迷宫是一个A行B列的矩阵,该迷宫有N个不同的出口与N个不同的入口,任一单元格不会既为入口又为出口。为了进一步探明与发掘该迷宫,N个考古队员分别从地上的N个不同的入口进入迷宫,并且计划从N个不同的出口出来。每个队员任意选择一个出口出来,但任意两名队员不会选择同一个出口。
迷宫中的每一格与其相邻的某些格相通。该迷宫设计非常精妙,在不知道具体机关的情况下,人一旦离开其所在格后,该格将迅速关闭,且再也不能开启,也就是说每一格仅能进入一次。更糟的是,迷宫中的每一格都有一定的危险性,专家们用1至100的整数表示,数值越大表示越危险。正因为如此,再加之每一格都不很宽敞,两人一起进入比较危险,所以规定不能两个人同时进入同一格。
为了队员们的安全着想,希望你能够编程求出如何使队员们所经过单元格的危险性总和最小。
【样例】
入口有两个:(1,1)即第一行第一列,(1,2)即第一行第二列
出口也有两个:(2,3)即第二行第三列,(3,4)即第三行第四列
两名队员的最好的行动方案之一,如上图红蓝箭头所示。危险程度之和最小为235。
【输入描述】
第一行是两个整数A与B(1≤A,B≤10),中间用空格分隔,表示该迷宫是A行B列的。第2行至第A+1行,每行有B个1至100以内的整数,表示该迷宫每一格的危险程度。
以下一行是一个整数K。接着K行每行有四个整数X0,Y0,X1,Y1,(1 ≤X0,X1≤A, 1≤Y0,Y1≤B) ,表示(X0,Y0),(X1,Y1)为相邻的两格,这两格互相相通。
接着一行是一个整数N(0≤N≤A*B/2),表示有N个出口与入口,保证出入口不会重合。
以下N行,每行有两个整数X0,Y0,表示每个入口的行列位置。
以下还有N行,每行有两个整数X1,Y1,表示每个出口的行列位置。
【输出描述】
输出仅一个数,若队员们不能全部到达指定目标位置,则输出-1;否则输出所有队员所经过的所有单元格的危险程度之和。
【输入样例】
3 420 30 40 3030 60 20 2020 15 20 20131 1 2 11 2 1 31 2 2 21 3 1 41 4 2 4
2 1 2 22 1 3 12 2 2 32 3 2 42 4 3 43 1 3 23 2 3 33 3 3 421 11 22 33 4
【输出样例】
235
noip前的题……我现在终于写对了…………
很水的拆点网络流……每个点拆成入点和出点然后入口和S相通出口和T相通就行了……然后最小费用最大流就行了
调的时候迷之WA是因为加边又加错了 = = 翔爷查了没多久就查出来了果然是大神OTL…………
建图的时候一定要注意。。( (x - 1) * B + y) ←这是是*B不是*A。。。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int inf = 0x3f3f3f;
int A, B, K, N;
int map[15][15];
int S, T;
int ans;
struct ed
{
int v, w, flow, next;
}e[35*35*8];
int k, head[35*35*4];
inline void adde(int u, int v, int f, int w)
{
e[k] = (ed){v, w, f, head[u]};
head[u] = k++;
e[k] = (ed){u, -w, 0, head[v]};
head[v] = k++;
}
inline int in(int x, int y)
{
return ( ( (x - 1) * B + y) << 1 ) - 1;
}
inline int out(int x, int y)
{
return ( (x - 1) * B + y) << 1;
}
inline void build_map()
{
memset(head, -1, sizeof(head));
for(int i = 1; i <= A; ++i)
{
for(int j = 1; j <= B; ++j)
{
scanf("%d", &map[i][j]);
adde(in(i, j), out(i, j), 1, map[i][j]);
}
}
S = 0; T = out(A, B) + 1;
cin >> K;
int x1, x2, y1, y2;
for(int i = 1; i <= K; ++i)
{
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
adde(out(x1, y1), in(x2, y2), 1, 0);
adde(out(x2, y2), in(x1, y1), 1, 0);
}
cin >> N;
for(int i = 1; i <= N; ++i)
{
scanf("%d%d", &x1, &y1);
adde(S, in(x1, y1), 1, 0);
}
for(int i = 1; i <= N; ++i)
{
scanf("%d%d", &x1, &y1);
adde(out(x1, y1), T, 1, 0);
}
}
int dis[35*35*4];
bool vis[35*35*4];
int pre[35*35*4];
int deltaf, flow;
queue <int> q;
bool spfa()
{
memset(dis, inf, sizeof(dis));
deltaf = inf;
//printf("%d\n",dis[S]);
dis[S] = 0;
q.push(S);
while(!q.empty())
{
int u = q.front(); q.pop();
vis[u] = 0;
for(int i = head[u]; ~i; i = e[i].next)
{
int v = e[i].v;
if(e[i].flow && dis[v] > dis[u] + e[i].w)
{
dis[v] = dis[u] + e[i].w;
pre[v] = i;
deltaf = min(e[i].flow, deltaf);
if(!vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
}
return dis[T] < inf;
}
int main()
{
freopen("maze.in", "r", stdin);
freopen("maze.out", "w", stdout);
cin >> A >> B;
build_map();
bool flag = 0;
while(spfa())
{
flag = 1;
for(int i = T; i != S; i = e[pre[i] ^ 1].v)
{
e[pre[i]].flow -= deltaf;
e[pre[i] ^ 1].flow += deltaf;
}
flow += deltaf;
ans += deltaf * dis[T];
}
if(flow >= N) cout << ans << endl;
else puts("-1");
return 0;
}
之前查错是对着小明的代码查错的…………嗯…………也贴上来吧免得以后找不到了…………其实还是想说java风看着好肉疼…………
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <queue>
using namespace std;
//Global Variables & Definetions
int A,B,K,N;
int map[110][110];
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
//End Global Variables & Definetions
//Network Flow!
//map
#define num(x,y) (((x) * B) + y)
#define in(x,y) num(x,y)
#define out(x,y) (num(x,y) + A * B)
#define S 209
#define SS 210
#define T 211
int h[220];
struct edge {
int v,next;
int cap,flow;
int cost;
}e[10000];
int ecnt = -1;
inline void _add(int u, int v, int cap, int cost) {
ecnt++;
e[ecnt].v = v;
e[ecnt].cap = cap;
e[ecnt].cost = cost;
e[ecnt].flow = 0;
e[ecnt].next = h[u];
h[u] = ecnt;
}
inline void adde(int u, int v, int cap, int cost) {
_add(u, v, cap, cost);
_add(v, u, 0, -cost);
}
void clear() {
memset(h, -1, sizeof(h));
ecnt = -1;
}
//End Map
//SPFA
queue<int> q;
int inq[220];
int dis[220], f[220], fe[220], maxf[220];
inline void init_spfa() {
while(!q.empty()) q.pop();
MS(inq,0);MS(dis,0x3f);
dis[S] = 0;
f[S] = fe[S] = -1;
maxf[S] = 0x7fffffff;
inq[S] = 1;
q.push(S);
}
//End SPFA
int maxflow() {
int ans = 0,flow = 0;
bool flag;
do {
init_spfa();
flag = 0;
while(!q.empty()) {
int u = q.front();q.pop();
inq[u] = 0;
for(int i = h[u];i != -1;i = e[i].next) if(e[i].flow < e[i].cap) {
int v = e[i].v;
if(dis[v] > dis[u] + e[i].cost) {
dis[v] = dis[u] + e[i].cost;
fe[v] = i;f[v] = u;
maxf[v] = min(maxf[u] ,e[i].cap - e[i].flow);
if(!inq[v]) {
q.push(v);
inq[v] = 1;
}
}
}
}
if(dis[T] < 0x3f3f3f3f) {
flag = 1;
ans += dis[T] * maxf[T];
flow += maxf[T];
for(int ptr = T;f[ptr] != -1;ptr = f[ptr]) {
int fa = fe[ptr];
e[fa].flow += maxf[T];
e[fa ^ 1].flow -= maxf[T];
}
}
} while(flag);
if(flow < N) return -1;
else return ans;
}
//End Network Flow!
//Main Structure
inline void ir() {
clear();
freopen("maze.in","r",stdin);
freopen("maze.out","w",stdout);
scanf("%d%d",&A,&B);
for(int i = 0;i < A;i++) {
for(int j = 0;j < B;j++) {
scanf("%d",&map[i][j]);
adde(in(i,j), out(i,j), 1, map[i][j]);
}
}
scanf("%d",&K);
int X0,Y0,X1,Y1;
for(int i = 0;i < K;i++) {
scanf("%d%d%d%d",&X0,&Y0,&X1,&Y1);
adde(out(X0 - 1,Y0 - 1), in(X1 - 1,Y1 - 1), 1, 0);
adde(out(X1 - 1,Y1 - 1), in(X0 - 1,Y0 - 1), 1, 0);
}
scanf("%d",&N);
for(int i = 0;i < N;i++) {
scanf("%d%d",&X0,&Y0);
adde(SS, in(X0 - 1,Y0 - 1), 1, 0);
}
for(int i = 0;i < N;i++) {
scanf("%d%d",&X1,&Y1);
adde(out(X1 - 1,Y1 - 1), T, 1, 0);
}
adde(S, SS, N, 0);
}
int main() {
ir();
printf("%d\n",maxflow());
return 0;
}