您的位置:首页 > 其它

POJ 2455 Secret Milking Machine (二分 + 最大流)

2016-01-08 07:32 531 查看
题目大意:

给出一张无向图,找出T条从1..N的路径,互不重复,求走过的所有边中的最大值最小是多少。

算法讨论:

首先最大值最小就提醒我们用二分,每次二分一个最大值,然后重新构图,把那些边权符合要求的边加入新图,在新图上跑网络流。

这题有许多注意的地方:

1、因为是无向图,所以我们在加正向边和反向边的时候,流量都是1,而不是正向边是1,反向边是0。

2、题目中说这样的路径可能不止t条,所以我们在最后二分判定的时候不能写 == t,而是要 >= t。

3、这题很容易T ,表示我T了N遍,弱菜啊。

Codes:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>

using namespace std;

int ns, ps, ts, te;
int l=0x3f3f3f3f, r, Mid;

struct Edge{
int from, to, dt;
}e[40000 + 5];

struct Dinic{
static const int maxn = 300 + 5;
static const int maxm = 80000 + 5;
static const int oo = 0x3f3f3f3f;

int n,m,s,t;
int tot;
int first[maxn],next[maxm];
int u[maxm],v[maxm],cap[maxm],flow[maxm];
int cur[maxn],dis[maxn];
bool vi[maxn];

Dinic(){tot=0;memset(first,-1,sizeof first);}
void Clear(){tot = 0;memset(first,-1,sizeof first);}
void Add(int from,int to,int cp,int flw){
u[tot] = from;v[tot] = to;cap[tot] = cp;flow[tot] = 0;
next[tot] = first[u[tot]];
first[u[tot]] = tot;
++ tot;
}
bool bfs(){
memset(vi,false,sizeof vi);
queue <int> q;
dis[s] = 0;vi[s] = true;
q.push(s);

while(!q.empty()){
int now = q.front();q.pop();
for(int i = first[now];i != -1;i = next[i]){
if(!vi[v[i]] && cap[i] > flow[i]){
vi[v[i]] = true;
dis[v[i]] = dis[now] + 1;
q.push(v[i]);
}
}
}
return vi[t];
}
int dfs(int x,int a){
if(x == t || a == 0) return a;
int flw=0,f;
int &i = cur[x];
for(i = first[x];i != -1;i = next[i]){
if(dis[x] + 1 == dis[v[i]] && (f = dfs(v[i],min(a,cap[i]-flow[i]))) > 0){
flow[i] += f;flow[i^1] -= f;
a -= f;flw += f;
if(a == 0) break;
}
}
return flw;
}
int MaxFlow(int s,int t){
this->s = s;this->t = t;
int flw=0;
while(bfs()){
memset(cur,0,sizeof cur);
flw += dfs(s,oo);
}
return flw;
}
}Net;

bool check(int mid){
Net.Clear();
for(int i = 1; i <= ps; ++ i){
if(e[i].dt <= mid){
Net.Add(e[i].from, e[i].to, 1, 0);
Net.Add(e[i].to, e[i].from, 1, 0);
}
}
return Net.MaxFlow(1, Net.n) >= ts;
}
int Solve(){
int ans;
while(l <= r){
Mid = l + (r - l) / 2;
if(check(Mid)){
ans = Mid; r = Mid - 1;
}
else l = Mid + 1;
}
return ans;
}
int main(){
int x, y, z;
scanf("%d%d%d", &ns, &ps, &ts);
Net.n = ns;te = 0;
for(int i = 1; i <= ps; ++ i){
scanf("%d%d%d", &x, &y, &z);
++ te;
e[te].from = x;e[te].to = y;e[te].dt = z;
l = min(l, z); r = max(z, r);
}
printf("%d\n", Solve());
return 0;
}


POJ 2455 T 版
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: