题目链接:
https://codeforces.com/problemset/problem/1423/B
题目大意:
给你n个工厂和n个机场,再给你m条道路,每条道路有一个修好天数,
问你在最早第几天时能让每个工厂能到机场送货(一个工厂只能选择
一个机场送货,一个机场只能给一个工厂送货)
输入与输出:
输入:
一个n机场和工厂个数,m道路条数
n行,每行3个数 u v d
u:第u个工厂
v:第v个机场
d:第d天修好
输出:
一个数,最早能送货的天数
如果道路全部修好了都不能成功送货,则输出-1
思路:
道路肯定越多,最终肯定越容易送货成功,
那么我们可以对天数进行二分,那么二分完后
剩下的图,我们可以用Dinic网络流来看是否能
送货成功。
(Dinic虽然普通图复杂度很高,但是对于二分图,就只有sqrt(n) * m的复杂度)
(!不能直接用费用流!)
Dinic建图方式:
一个源点链接所有工厂,容量为1(每个工厂只能选择一个机场)
工厂连接机场容量 >= 1即可
机场再链接一个汇点,容量也要为1(每个机场只能给一个工厂送货)
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int maxn = 2e4 + 5;
const int maxe = 3e5 + 5;
struct edgeInfo
{
int ss;
int ee;
int ww;
int dd;
edgeInfo() {}
edgeInfo(int ss, int ee, int ww, int dd)
:ss(ss), ee(ee), ww(ww), dd(dd){}
bool operator < (const edgeInfo &B) const {
return dd < B.dd;
}
};
struct edge
{
int ee;
int ww;
edge(int ee, int ww)
:ee(ee), ww(ww) {}
};
edgeInfo allE[maxe];
vector<edge> vee;
vector<vector<int>> vec(maxn);
int vis[maxn], dep[maxn];
int n, m;
inline int getS()
{
return 0;
}
inline int getE()
{
return 2 * n + 1;
}
inline int get0ID(int ii)
{
return ii;
}
inline int get1ID(int ii)
{
return ii + n;
}
inline void AddEdge(int s, int e, int w)
{
vee.push_back(edge(e, w));
vee.push_back(edge(s, 0));
vec[s].push_back(vee.size() - 2);
vec[e].push_back(vee.size() - 1);
}
inline void AddEdge(int ii)
{
int s = allE[ii].ss;
int e = allE[ii].ee;
int w = allE[ii].ww;
AddEdge(s, e, w);
}
bool BFS(int spoint)
{
memset(dep, 0, sizeof(dep));
queue<int> que;
que.push(spoint);
dep[spoint] = 1;
while (que.size()) {
int st = que.front();
//printf("bfs: st=%d dep=%d\n", st, dep[st]);
que.pop();
for (int i = 0; i < vec[st].size(); i++) {
int e = vee[vec[st][i]].ee;
int w = vee[vec[st][i]].ww;
if (!w) continue;
if (dep[e]) continue;
dep[e] = dep[st] + 1;
que.push(e);
}
}
return dep[getE()];
}
int DFS(int ii, int fl)
{
if (ii == getE())
return fl;
int tfl = 0;
for (int &i = vis[ii]; i < vec[ii].size(); i++) {
int w = vee[vec[ii][i]].ww;
int e = vee[vec[ii][i]].ee;
if (!w) continue;
if (dep[e] != dep[ii] + 1) continue;
int nfl = DFS(e, min(fl, w));
fl -= nfl;
tfl += nfl;
vee[vec[ii][i]].ww -= nfl;
vee[vec[ii][i] ^ 1].ww += nfl;
if (fl == 0) break;
}
if (!tfl) dep[ii] = 0;
return tfl;
}
bool chk(int dd)
{
vee.clear();
for (int i = 0; i < maxn; i++)
vec[i].clear();
for (int i = 1; i <= m; i++) {
if (allE[i].dd > dd) break;
AddEdge(i);
}
for (int i = 1; i <= n; i++) {
AddEdge(getS(), get0ID(i), 1);
AddEdge(get1ID(i), getE(), 1);
}
int flow = 0;
while (BFS(getS())) {
memset(vis, 0, sizeof(vis));
int tflow = DFS(getS(), n);
flow += tflow;
}
//printf("dd=%d flow=%d\n", dd, flow);
return flow >= n;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
int s, e, d;
scanf("%d%d%d", &s, &e, &d);
e = get1ID(e);
s = get0ID(s);
allE[i] = edgeInfo(s, e, 1, d);
}
sort(allE + 1, allE + 1 + m);
int lw = 1;
int hg = 1e9 + 7;
int mm, res = -1;
while (lw <= hg) {
mm = (lw + hg) >> 1;
if (chk(mm)) hg = mm - 1, res = mm;
else lw = mm + 1;
}
printf("%d\n", res);
return 0;
}