您的位置:首页 > 其它

poj 2391 二分+最大流 (dinic模板+优化)

2013-09-09 16:17 489 查看
/*
* =====================================================================================
*
*       Filename:  2391.cpp
*        Version:  1.0
*        Created:  09/08/2013 10:04:09 AM
*       Revision:  none
*       Compiler:  GNU C++
*
*      Just like you,wait you forever~~
*
* =====================================================================================
*/
#include <set>
#include <map>
#include <list>
#include <queue>
#include <stack>
#include <cmath>
#include <string>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define PB              push_back
#define SIZE(x)         (int)x.size()
#define clr(x,y)        memset(x,y,sizeof(x))
#define MP(x,y)         make_pair(x,y)
#define RS(n)           scanf ("%s", n)
#define ALL(t)          (t).begin(),(t).end()
#define FOR(i,n,m)      for (int i = n; i <= m; i ++)
#define ROF(i,n,m)      for (int i = n; i >= m; i --)
#define IT              iterator
#define FF              first
#define SS              second

typedef long long               ll;
typedef unsigned int            uint;
typedef unsigned long long      ull;
typedef vector<int>             vint;
typedef vector<string>          vstring;
typedef pair<int, int>          PII;

void RI (int& x){
x = 0;
char c = getchar ();
while (c == ' '||c == '\n')	c = getchar ();
bool flag = 1;
if (c == '-'){
flag = 0;
c = getchar ();
}
while (c >= '0' && c <= '9'){
x = x * 10 + c - '0';
c = getchar ();
}
if (!flag)	x = -x;
}
void RII (int& x, int& y){RI (x), RI (y);}
void RIII (int& x, int& y, int& z){RI (x), RI (y), RI (z);}
void RC (char& c){
c = getchar ();
while (c == ' '||c == '\n')     c = getchar ();
}
char RC (){
char c = getchar ();
while (c == ' '||c == '\n')     c = getchar ();
return c;
}
void PI (int n){
char s[15];
int ed = 14, st = 14;
while (n){
s[st --] = n%10;
n /= 10;
}
FOR (i, st+1, ed)       putchar (s[i] + '0');
}

/**************************************END define***************************************/

const ll mod = 1e9+7;
const ll LINF = 1e18;
const int INF = 1e9;
const double EPS = 1e-8;

const int N = 505;
const int M = 600000;

struct Edge{
int v, w, next;
}g[M];

int n, w1
, w2
, head[N*2+2], cnt, st, ed, dis[N*2+2], cur[N*2+2];
ll a

;

void init (){
clr (head, -1);
cnt = 0;
}

void addedge (int u, int v, int w){
g[cnt].v = v, g[cnt].w = w, g[cnt].next = head[u], head[u] = cnt ++;
g[cnt].v = u, g[cnt].w = 0, g[cnt].next = head[v], head[v] = cnt ++;
}

bool bfs (){
clr (dis, -1);
dis[st] = 0;
queue<int> q;
q.push (st);
while (SIZE(q)){
int u = q.front ();
q.pop ();
for (int i = head[u]; ~i; i = g[i].next){
int v = g[i].v, w = g[i].w;
if (w > 0 && dis[v] == -1){
dis[v] = dis[u]+1;
q.push (v);
if (v == ed)    return true;
}
}
}
return dis[ed] != -1;
}

int dfs (int u, int limit){
if (u == ed)    return limit;
int ans = 0;
for (int& i = cur[u]; ~i; i = g[i].next){
int v = g[i].v, w = g[i].w;
if (w > 0 && dis[v] == dis[u]+1){
int t = dfs (v, min (limit-ans, w));
ans += t;
g[i].w -= t;
g[i^1].w += t;
if (limit == ans)       break;
}
}
if (!ans)       dis[u] = -1;
return ans;
}

int dinic (){
int ans = 0;
while (bfs ()){
FOR (i, st, ed){
cur[i] = head[i];
}
ans += dfs (st, INF);
}
return ans;
}

bool cal (ll limit, ll sum){
init ();
FOR (i, 1, n){
addedge (i, i+N, w1[i]);
addedge (st, i, w1[i]);
addedge (i, ed, w2[i]);
FOR (j, 1, n){
if (a[i][j] <= limit){
addedge (i+N, j, INF);
}
}
}
return dinic () == sum;
}

ll binary_search (){
st = 0, ed = N*2+1;
ll sum = 0;
FOR (i, 1, n){
sum += w1[i];
}
ll low = 0, high = LINF-1;
while (low <= high){
ll mid = (low + high)/2;
if (cal (mid, sum))          high = mid-1;
else                         low = mid+1;
}
if (high == LINF-1)       return -1;
return low;
}

int main (){
int m;
RII (n, m);
ll sum = 0;
FOR (i, 1, n){
RII (w1[i], w2[i]);
sum += w1[i];
}
FOR (i, 1, n){
FOR (j, 1, n){
a[i][j] = LINF;
}
}
while (m --){
int u, v, w;
RIII (u, v, w);
a[u][v] = min (a[u][v], (ll)w);
a[v][u] = a[u][v];
}
FOR (k, 1, n){
FOR (i, 1, n){
FOR (j, 1, n){
a[i][j] = min (a[i][j], a[i][k] + a[k][j]);
}
}
}
printf ("%lld\n", binary_search ());
//st = 0, ed = N*2+1;
//cal (110, sum);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: