# 平面圖最小割 BZOJ1001: [BeiJing2006]狼抓兔子 BZOJ 2007: [Noi2010]海拔

## 1001: [BeiJing2006]狼抓兔子

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 5710  Solved: 1290
[Submit][Status][Discuss]

3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6

## Sample Output

14

/*
*	分析：
*		平面图最小割转化为最短路问题。
* */
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

const int X = 1000002*2;
const int inf = 1e9;

#define debug puts("here");

int id[2][1001][1001];

struct node{
int y,dis,next;
}edge[X*6];

int ds,dt,tot;
int n,m;
int dis[X];
int po[X],tol;

edge[++tol].y = y;
edge[tol].dis = w;
edge[tol].next = po[x];
po[x] = tol;

edge[++tol].y = x;
edge[tol].dis = w;
edge[tol].next = po[y];
po[y] = tol;
}

void build(){
tot = 0;
for(int j=1;j<n;j++)
for(int k=1;k<m;k++)
for(int i=0;i<2;i++)
id[i][j][k] = ++tot;
ds = ++ tot;
dt = ++ tot;

memset(po,0,sizeof(po));
tol = 0;
int w;

int ok = 0;
int check = n*(m-1)+(n-1)*m+(n-1)*(m-1);
/***********  1  ******************/
for(int i=1;i<m;i++){
scanf("%d",&w);
ok ++;
}

for(int i=2;i<n;i++){
for(int j=1;j<m;j++){
scanf("%d",&w);
ok ++;
}
}

for(int i=1;i<m;i++){
scanf("%d",&w);
ok ++;
}
/***********  1  ******************/

/***********  2  ******************/
for(int i=1;i<n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&w);
ok ++;
if(j==1)
else if(j==m)
else
}
}
/***********  2  ******************/

for(int i=1;i<n;i++){
for(int j=1;j<m;j++){
if(ok>=check)
debug;
scanf("%d",&w);
ok ++;
}
}
}

struct state{
int x,w;
state(){}
state(int _x,int _w):x(_x),w(_w){}
friend bool operator < (state a,state b){
return a.w > b.w;
}
};

priority_queue<state> q;

int dijkstra(){
while(q.size())
q.pop();
for(int i=1;i<=tot;i++)
dis[i] = inf;
dis[ds] = 0;
q.push(state(ds,0));
while(q.size()){
state tmp = q.top();;
q.pop();
int x = tmp.x;
if(tmp.w>dis[x])
continue;
if(x==dt)
return tmp.w;
for(int i=po[x];i;i=edge[i].next){
int y = edge[i].y;
int cur = dis[x]+edge[i].dis;
if(cur < dis[y]){
dis[y] = cur;
q.push(state(y,cur));
}
}
}
return -1;
}

int main(){
while(cin>>n>>m){
if(n==1||m==1){
int ans = inf;
int x;
for(int i=1;i<max(n,m);i++){
scanf("%d",&x);
ans = min(ans,x);
}
cout<<ans<<endl;
continue;
}
build();
cout<<dijkstra()<<endl;
}
return 0;
}


## 2007: [Noi2010]海拔

Time Limit: 20 Sec  Memory Limit: 552 MB
Submit: 778  Solved: 332
[Submit][Status][Discuss]

## Description

YT市是一个规划良好的城市，城市被东西向和南北向的主干道划分为n×n个区域。简单起见，可以将YT市看作一个正方形，每一个区域也可看作一个正方形。从而，YT城市中包括(n+1)×(n+1)个交叉路口和2n×(n+1)条双向道路（简称道路），每条双向道路连接主干道上两个相邻的交叉路口。下图为一张YT市的地图(n = 2)，城市被划分为2×2个区域，包括3×3个交叉路口和12条双向道路。 小Z作为该市的市长，他根据统计信息得到了每天上班高峰期间YT市每条道路两个方向的人流量，即在高峰期间沿着该方向通过这条道路的人数。每一个交叉路口都有不同的海拔高度值，YT市市民认为爬坡是一件非常累的事情，每向上爬h的高度，就需要消耗h的体力。如果是下坡的话，则不需要耗费体力。因此如果一段道路的终点海拔减去起点海拔的值为h(注意h可能是负数)，那么一个人经过这段路所消耗的体力是max{0, h}（这里max{a, b}表示取a, b两个值中的较大值）。 小Z还测量得到这个城市西北角的交叉路口海拔为0，东南角的交叉路口海拔为1(如上图所示)，但其它交叉路口的海拔高度都无法得知。小Z想知道在最理想的情况下（即你可以任意假设其他路口的海拔高度），每天上班高峰期间所有人爬坡所消耗的总体力和的最小值。

1

1

2

3

4

5

6

7

8

## Sample Output

3

【样例说明】

【数据规模】

/*

*/
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

#define lx(x) (x<<1)
#define rx(x) (x<<1|1)
#define debug puts("here")
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
#define pb push_back
#define RD(n) scanf("%d",&n)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)

/******** program ********************/

const int MAXN = 505*505;
const int MAXM = MAXN*16;

int po[MAXN],tol,n,m,s,t;
int dis[MAXN];
bool use[MAXN];

struct Edge{
int y,val,next;
}edge[MAXM];

struct node{
int x;
int val;
node(){}
node(int _x,int _val):x(_x),val(_val){}
friend bool operator < (node a,node b){
return a.x>b.x;
}
};

priority_queue<node> q;

edge[++tol].y = y;
edge[tol].val = val;
edge[tol].next = po[x];
po[x] = tol;
}

int dijkstra(){
memset(dis,0x7f,sizeof(dis));

q.push(node(s,0));
dis[s] = 0;

while(q.size()){
node p = q.top();
q.pop();
int x = p.x;
if(p.val>dis[x]) // 小優化
continue;
if(x==t)
return p.val;
for(int i=po[x];i;i=edge[i].next){
int y = edge[i].y;
int cur = edge[i].val+dis[x];
if(cur<dis[y]){
dis[y] = cur;
q.push( node(y,cur) );
}
}
}
while(true)
;
return -1;
}

int id(int x,int y){
return x*n-n+y;
}

void init(){
RD(n);
int val;
s = n*n+1;
t = s+1;

/******************************************/

rep1(i,n){
RD(val);
}
rep1(i,n-1){
rep1(j,n){
RD(val);
}
}
rep1(i,n){
RD(val);
}

/******************************************/

rep1(i,n){
RD(val);

rep1(j,n-1){
RD(val);
}

RD(val);
}

/******************************************/

rep1(i,n)   RD(val); // 這樣的邊沒有意義
rep1(i,n-1){
rep1(j,n){
RD(val);
}
}
rep1(i,n)   RD(val);

/******************************************/

rep1(i,n){
RD(val);
rep1(j,n-1){
RD(val);
}
RD(val);
}
}

int spfa(){
memset(dis,0x7f,sizeof(dis));
memset(use,false,sizeof(use));
queue<int> q;
q.push(s);
dis[s] = 0;
while(q.size()){
int x = q.front();
q.pop();
use[x] = false;
for(int i=po[x];i;i=edge[i].next){
int y = edge[i].y;
int tmp = edge[i].val+dis[x];
if(tmp<dis[y]){
dis[y] = tmp;
if(!use[y]){
use[y] = true;
q.push(y);
}
}
}
}
return dis[t];
}

int main(){

#ifndef ONLINE_JUDGE
freopen("sum.in","r",stdin);
//freopen("sum.out","w",stdout);
#endif

init();
//cout<<dijkstra()<<endl; // 堆優化的dijkstra
cout<<spfa()<<endl;       // spfa

return 0;
}


posted @ 2013-04-19 23:09  yejinru  阅读(473)  评论(0编辑  收藏  举报