原题:http://poj.org/problem?id=2391
#include<cstdio> #include<cstring> #include<string> #include<queue> #include<vector> #define inf 1LL<<60 #define ll long long using namespace std; const int maxn = 500; const int maxm = 50000; int f, p; int num_nodes; ll dis[maxn][maxn]; int a[maxn][2]; struct Edge { int from, to; ll flow, cap; }edge[maxm*2]; vector<int>G[maxn]; int edgenum; void add(int u, int v, ll c) { edge[edgenum].from = u; edge[edgenum].to = v; edge[edgenum].flow = 0; edge[edgenum].cap = c; edgenum++; edge[edgenum].from = v; edge[edgenum].to = u; edge[edgenum].flow = 0; edge[edgenum].cap = 0; edgenum++; G[u].push_back(edgenum-2); G[v].push_back(edgenum-1); } int deep[maxn]; bool vis[maxn]; void BFS(int s, int t) { queue<int>Q; memset(vis, false, sizeof vis); Q.push(t); vis[t] = true; deep[t] = 0; while(!Q.empty()) { int now = Q.front(); Q.pop(); for(int i = 0;i<(int)G[now].size();i++) { int v = edge[G[now][i]].to; if(!vis[v]) { deep[v] = deep[now] + 1; vis[v] = true; Q.push(v); } } } } int gap[maxn]; int cur[maxn]; int front[maxn]; int Augment(int s, int t) { ll minflow = inf; int begin = t; while(begin != s) { Edge& e = edge[front[begin]]; minflow = min(minflow, e.cap - e.flow); begin = e.from; } begin = t; while(begin != s) { edge[front[begin]].flow += minflow; edge[front[begin]^1].flow -= minflow; begin = edge[front[begin]].from; } return minflow; } ll Maxflow(int s, int t) { ll flow = 0; BFS(s, t); memset(gap, 0, sizeof gap); memset(cur, 0, sizeof cur); for(int i = 0;i<num_nodes;i++) gap[deep[i]]++; int begin = s; while(deep[s] < num_nodes) { if(begin == t) { flow += Augment(s, t); begin = s; } bool flag = false; for(int i = cur[begin];i<(int)G[begin].size();i++) { Edge& e = edge[G[begin][i]]; if(e.cap > e.flow && deep[begin] == deep[e.to] + 1) { front[e.to] = G[begin][i]; cur[begin] = i; flag = true; begin = e.to; break; } } if(!flag) { int k = num_nodes-1; for(ll i = 0;i<(int)G[begin].size();i++) { Edge& e = edge[G[begin][i]]; if(e.cap > e.flow) k = min(k, deep[e.to]); } if(--gap[deep[begin]] == 0) break; gap[deep[begin] = k+1]++; cur[begin] = 0; if(begin != s) begin = edge[front[begin]].from; } } return flow; } void init() { for(int i = 0;i<num_nodes+2;i++) G[i].clear(); edgenum = 0; memset(deep, 0, sizeof deep); } void Floyd() { for(int k = 1;k<=f;k++) { for(int i = 1;i<=f;i++) { for(int j = 1;j<=f;j++) dis[i][j] = min(dis[i][j], dis[i][k]+dis[k][j]); } } } int main() { while(~scanf("%d%d", &f, &p)) { ll sum = 0; for(int i = 1;i<=f;i++) { scanf("%d%d", &a[i][0], &a[i][1]); sum += a[i][0]; } for(int i = 1;i<=f;i++) { for(int j = 1;j<=f;j++) { if(i == j) dis[i][j] = 0; else dis[i][j] = inf; } } for(int i = 1;i<=p;i++) { int u, v, d; scanf("%d%d%d", &u, &v, &d); dis[u][v] = dis[v][u] = min(dis[u][v], (ll)d); } Floyd(); ll l = 0, r = 0; for(int i = 1;i<=f;i++) { for(int j = 1;j<=f;j++) if(dis[i][j] < inf) r = max(r, dis[i][j]); } ll ans = inf; int s = 0, t = 2*f+1; num_nodes = t+1; bool flag = false; while(l <= r) { ll mid = (l+r)/2; init(); for(int i = 1;i<=f;i++) { add(s, i, a[i][0]); add(f+i, t, a[i][1]); } for(int i = 1;i<=f;i++) { for(int j = 1;j<=f;j++) { if(dis[i][j] <= mid) add(i, f+j, inf); } } ll flow = Maxflow(s, t); if(flow == sum) { flag = true; r = mid - 1; ans = min(ans, mid); } else l = mid + 1; } if(!flag) ans = -1; printf("%lld\n", ans); } return 0; }
时间: 2024-10-14 13:45:58