题目背景
这本是一个非常简单的问题,然而奶牛们由于下雨已经非常混乱,无法完成这一计算,于是这个任务就交给了你。(奶牛混乱的原因看题目描述)
题目描述
在一个农场里有 nn 块田地。某天下午,有一群牛在田地里吃草,他们分散在农场的诸多田地上,农场由 mm 条无向的路连接,每条路有不同的长度。
突然,天降大雨,奶牛们非常混乱,想要快点去躲雨。已知每个田地都建立有一个牛棚,但是每个牛棚只能容纳一定数量的牛躲雨,如果超过这个数量,那多出的牛只能去别的田地躲雨。奶牛们每移动 11 的距离花费 11 时间,奶牛们想知道它们全部都躲进牛棚,最少需要多少时间。(即最后一头奶牛最少要花多久才能躲进牛棚)。
输入格式
第一行有两个整数,分别代表田地数 nn 和道路数 mm。
接下来 nn 行,每行两个整数,第 (i + 1)(i+1) 行的整数 s_i, p_isi,pi 分别表示第 ii 块田地的牛的数量以及该田地的牛棚最多可以容纳多少牛。
接下来 mm 行,每行三个整数 u, v, wu,v,w,代表存在一条长度为 ww 的连接 uu 和 vv 的道路。
输出格式
输出一行一个整数表示所有奶牛全都躲进牛棚所用的最少时间。如果无法使全部奶牛都躲进牛棚,输出 -1−1。
输入输出样例
输入 #1
3 4 7 2 0 4 2 6 1 2 40 3 2 70 2 3 90 1 3 120
输出 #1
View Code
110
思路
这道题和之前EOJ月赛上的一道题差不多。
建图很好想。
对每个 i 点拆开,入点装过路牛,连向S。
出点装雨棚里能待的牛,连向T。
出入点之间的容量显然为雨棚的容量。
用 Floyd 预处理出每个雨棚之间的距离
二分枚举牛进雨棚的时间
以此作为限制条件建图
通过限定连边的长度来限制时间
当恰好流量等于牛的数量时,
说明此时所有牛能进雨棚
注意开 long long
CODE
1 #include <bits/stdc++.h> 2 #define dbg(x) cout << #x << "=" << x << endl 3 #define eps 1e-8 4 #define pi acos(-1.0) 5 6 using namespace std; 7 typedef long long LL; 8 9 const LL inf = 1e13; 10 11 template<class T>inline void read(T &res) 12 { 13 char c;T flag=1; 14 while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0'; 15 while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag; 16 } 17 18 namespace _buff { 19 const size_t BUFF = 1 << 19; 20 char ibuf[BUFF], *ib = ibuf, *ie = ibuf; 21 char getc() { 22 if (ib == ie) { 23 ib = ibuf; 24 ie = ibuf + fread(ibuf, 1, BUFF, stdin); 25 } 26 return ib == ie ? -1 : *ib++; 27 } 28 } 29 30 int qread() { 31 using namespace _buff; 32 int ret = 0; 33 bool pos = true; 34 char c = getc(); 35 for (; (c < '0' || c > '9') && c != '-'; c = getc()) { 36 assert(~c); 37 } 38 if (c == '-') { 39 pos = false; 40 c = getc(); 41 } 42 for (; c >= '0' && c <= '9'; c = getc()) { 43 ret = (ret << 3) + (ret << 1) + (c ^ 48); 44 } 45 return pos ? ret : -ret; 46 } 47 48 const int maxn = 2007; 49 50 int n, m; 51 LL s[maxn], P[maxn]; 52 int S, T; 53 54 struct edge{ 55 int from,to; 56 LL cap,flow; 57 }; 58 59 struct isap 60 { 61 int n,s,t; 62 LL p[maxn],d[maxn],cur[maxn],num[maxn]; 63 vector<int>g[maxn]; 64 vector<edge> edges; 65 void init(int n,int s,int t) { 66 this->n = n; 67 this->s = s; 68 this->t = t; 69 for(int i = 0;i <= 500;i++) g[i].clear(); 70 edges.clear(); 71 memset(p, 0, sizeof(p)); 72 memset(d, 0, sizeof(d)); 73 memset(cur, 0, sizeof(cur)); 74 memset(num, 0, sizeof(num)); 75 } 76 void addegde(int from,int to,int cap) { 77 edges.push_back((edge){from, to, cap, 0}); 78 edges.push_back((edge){to, from, 0, 0}); 79 int m = edges.size(); 80 g[from].push_back(m-2); 81 g[to].push_back(m-1); 82 } 83 84 LL augment() {///找增广路 85 int d = edges.size(); 86 // for ( int i = 0; i < d; ++i ) { 87 // printf("from:%d to:%d cap:%d ",edges[i].from,edges[i].to,edges[i].cap); 88 // } 89 int x = t; 90 LL a = inf; 91 92 while(x!=s) { 93 a = min(a, edges[p[x]].cap - edges[p[x]].flow); 94 x = edges[p[x]].from; 95 // printf("edges[%d].from:%d ",p[x], edges[p[x]].from); 96 // printf("x:%d s:%d ",x, s); 97 } 98 x=t; 99 while(x != s) { 100 edges[p[x]].flow += a; 101 edges[p[x]^1].flow = -a; 102 x = edges[p[x]].from; 103 } 104 return a; 105 } 106 107 LL maxflow() {///更新最大流 108 LL flow = 0; 109 memset(num, 0, sizeof(num)); 110 memset(cur, 0, sizeof(cur)); 111 //memset(d, 0, sizeof(d)); 112 for(int i = 1; i <= n; i++) num[d[i]]++; 113 int x = s; 114 115 //printf("d[%d]:%d ",s, d[s]); 116 while(d[s] < n) {///最长的一条链上,最大的下标是nv-1,如果大于等于nv说明已断层 117 //printf("d[%d]:%d ", s, d[s]); 118 if(x == t) { 119 flow += augment(); 120 x = s;//回退 121 } 122 bool ok = 0; 123 for(int i = cur[x]; i < g[x].size(); i++) { 124 edge e = edges[g[x][i]]; 125 //printf("e->to:%d ",e.to); 126 if(d[x] == d[e.to] + 1 && e.cap > e.flow) { 127 p[e.to] = g[x][i]; 128 cur[x] = i;x = e.to; 129 ok = 1; 130 break; 131 } 132 } 133 if(!ok) { 134 LL m = n-1; 135 for(int i = 0; i < g[x].size();i++) { 136 edge &e=edges[g[x][i]]; 137 if(e.cap>e.flow) m=min(m,d[e.to]); 138 } 139 num[d[x]]--; 140 if(!num[d[x]]) break; 141 d[x] = m+1; 142 num[d[x]]++; 143 cur[x] = 0; 144 if(x != s) x = edges[p[x]].from; 145 } 146 } 147 return flow; 148 } 149 }ISAP; 150 151 LL dis[207][207]; 152 153 inline int id(int a, int b) { 154 return (a - 1) * n + b; 155 } 156 157 bool check(LL x) { 158 ISAP.init(n * 3, 0, n * 2 + 1); 159 for ( int i = 1; i <= n; ++i ) { 160 for ( int j = 1; j <= n; ++j ) { 161 //printf("dis[%d][%d]:%d ",i, j, dis[i][j]); 162 if(dis[i][j] != inf && dis[i][j] <= x) { 163 ISAP.addegde(i, j + n, inf); 164 //printf("i:%d j+n:%d ",i, j + n); 165 //ISAP.addegde(j + n, i, 0); 166 } 167 } 168 } 169 int S = 0, T = n * 2 + 1; 170 LL sum = 0; 171 for ( int i = 1; i <= n; ++i ) { 172 ISAP.addegde(S, i, s[i]); 173 sum += s[i]; 174 ISAP.addegde(i + n, T, P[i]); 175 ISAP.addegde(i, i + n, inf); 176 } 177 LL res = ISAP.maxflow(); 178 // dbg(res); 179 // dbg(sum); 180 return res == sum; 181 } 182 183 int main() 184 { 185 //freopen("data.txt", "r", stdin); 186 read(n); read(m); 187 for ( int i = 1; i <= n; ++i ) { 188 read(s[i]); read(P[i]); 189 } 190 for ( int i = 1; i <= n; ++i ) { 191 for ( int j = 1; j <= n; ++j ) { 192 if(i == j) 193 dis[i][j] = dis[j][i] = 0; 194 else { 195 dis[i][j] = dis[j][i] = inf; 196 } 197 } 198 } 199 for ( int i = 1; i <= m; ++i ) { 200 LL u, v, c; 201 read(u); read(v); read(c); 202 if(dis[u][v] == inf || dis[u][v] > c) dis[u][v] = dis[v][u] = c; 203 //ISAP.addegde(u, v, c); 204 } 205 LL l = 0, r = 0, mid; 206 for ( int k = 1; k <= n; ++k ) { 207 for ( int i = 1; i <= n; ++i ) { 208 for ( int j = 1; j <= n; ++j ) { 209 if(i == j) { 210 dis[i][j] = 0; 211 } 212 else { 213 if(dis[i][j] > dis[i][k] + dis[k][j]) { 214 dis[i][j] = dis[i][k] + dis[k][j]; 215 } 216 } 217 r = max(r, dis[i][j]); 218 } 219 } 220 } 221 LL ans = -1; 222 while(l <= r) { 223 mid = (l + r) >> 1; 224 //dbg(mid); 225 if(check(mid)) { 226 ans = mid, r = mid - 1; 227 } 228 else { 229 l = mid + 1; 230 } 231 } 232 cout << ans << endl; 233 return 0; 234 }
#include <bits/stdc++.h>
#define dbg(x) cout << #x << "=" << x << endl
#define eps 1e-8
#define pi acos(-1.0)
using namespace std;
typedef long long LL;
const LL inf = 1e13;
template<class T>inline void read(T &res)
{
char c;T flag=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
namespace _buff {
const size_t BUFF = 1 << 19;
char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
char getc() {
if (ib == ie) {
ib = ibuf;
ie = ibuf + fread(ibuf, 1, BUFF, stdin);
}
return ib == ie ? -1 : *ib++;
}
}
int qread() {
using namespace _buff;
int ret = 0;
bool pos = true;
char c = getc();
for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
assert(~c);
}
if (c == '-') {
pos = false;
c = getc();
}
for (; c >= '0' && c <= '9'; c = getc()) {
ret = (ret << 3) + (ret << 1) + (c ^ 48);
}
return pos ? ret : -ret;
}
const int maxn = 2007;
int n, m;
LL s[maxn], P[maxn];
int S, T;
struct edge{
int from,to;
LL cap,flow;
};
struct isap
{
int n,s,t;
LL p[maxn],d[maxn],cur[maxn],num[maxn];
vector<int>g[maxn];
vector<edge> edges;
void init(int n,int s,int t) {
this->n = n;
this->s = s;
this->t = t;
for(int i = 0;i <= 500;i++) g[i].clear();
edges.clear();
memset(p, 0, sizeof(p));
memset(d, 0, sizeof(d));
memset(cur, 0, sizeof(cur));
memset(num, 0, sizeof(num));
}
void addegde(int from,int to,int cap) {
edges.push_back((edge){from, to, cap, 0});
edges.push_back((edge){to, from, 0, 0});
int m = edges.size();
g[from].push_back(m-2);
g[to].push_back(m-1);
}
LL augment() {///找增广路
int d = edges.size();
// for ( int i = 0; i < d; ++i ) {
// printf("from:%d to:%d cap:%d
",edges[i].from,edges[i].to,edges[i].cap);
// }
int x = t;
LL a = inf;
while(x!=s) {
a = min(a, edges[p[x]].cap - edges[p[x]].flow);
x = edges[p[x]].from;
// printf("edges[%d].from:%d
",p[x], edges[p[x]].from);
// printf("x:%d s:%d
",x, s);
}
x=t;
while(x != s) {
edges[p[x]].flow += a;
edges[p[x]^1].flow = -a;
x = edges[p[x]].from;
}
return a;
}
LL maxflow() {///更新最大流
LL flow = 0;
memset(num, 0, sizeof(num));
memset(cur, 0, sizeof(cur));
//memset(d, 0, sizeof(d));
for(int i = 1; i <= n; i++) num[d[i]]++;
int x = s;
//printf("d[%d]:%d
",s, d[s]);
while(d[s] < n) {///最长的一条链上,最大的下标是nv-1,如果大于等于nv说明已断层
//printf("d[%d]:%d
", s, d[s]);
if(x == t) {
flow += augment();
x = s;//回退
}
bool ok = 0;
for(int i = cur[x]; i < g[x].size(); i++) {
edge e = edges[g[x][i]];
//printf("e->to:%d
",e.to);
if(d[x] == d[e.to] + 1 && e.cap > e.flow) {
p[e.to] = g[x][i];
cur[x] = i;x = e.to;
ok = 1;
break;
}
}
if(!ok) {
LL m = n-1;
for(int i = 0; i < g[x].size();i++) {
edge &e=edges[g[x][i]];
if(e.cap>e.flow) m=min(m,d[e.to]);
}
num[d[x]]--;
if(!num[d[x]]) break;
d[x] = m+1;
num[d[x]]++;
cur[x] = 0;
if(x != s) x = edges[p[x]].from;
}
}
return flow;
}
}ISAP;
LL dis[207][207];
inline int id(int a, int b) {
return (a - 1) * n + b;
}
bool check(LL x) {
ISAP.init(n * 3, 0, n * 2 + 1);
for ( int i = 1; i <= n; ++i ) {
for ( int j = 1; j <= n; ++j ) {
//printf("dis[%d][%d]:%d
",i, j, dis[i][j]);
if(dis[i][j] != inf && dis[i][j] <= x) {
ISAP.addegde(i, j + n, inf);
//printf("i:%d j+n:%d
",i, j + n);
//ISAP.addegde(j + n, i, 0);
}
}
}
int S = 0, T = n * 2 + 1;
LL sum = 0;
for ( int i = 1; i <= n; ++i ) {
ISAP.addegde(S, i, s[i]);
sum += s[i];
ISAP.addegde(i + n, T, P[i]);
ISAP.addegde(i, i + n, inf);
}
LL res = ISAP.maxflow();
// dbg(res);
// dbg(sum);
return res == sum;
}
int main()
{
//freopen("data.txt", "r", stdin);
read(n); read(m);
for ( int i = 1; i <= n; ++i ) {
read(s[i]); read(P[i]);
}
for ( int i = 1; i <= n; ++i ) {
for ( int j = 1; j <= n; ++j ) {
if(i == j)
dis[i][j] = dis[j][i] = 0;
else {
dis[i][j] = dis[j][i] = inf;
}
}
}
for ( int i = 1; i <= m; ++i ) {
LL u, v, c;
read(u); read(v); read(c);
if(dis[u][v] == inf || dis[u][v] > c) dis[u][v] = dis[v][u] = c;
//ISAP.addegde(u, v, c);
}
LL l = 0, r = 0, mid;
for ( int k = 1; k <= n; ++k ) {
for ( int i = 1; i <= n; ++i ) {
for ( int j = 1; j <= n; ++j ) {
if(i == j) {
dis[i][j] = 0;
}
else {
if(dis[i][j] > dis[i][k] + dis[k][j]) {
dis[i][j] = dis[i][k] + dis[k][j];
}
}
r = max(r, dis[i][j]);
}
}
}
LL ans = -1;
while(l <= r) {
mid = (l + r) >> 1;
//dbg(mid);
if(check(mid)) {
ans = mid, r = mid - 1;
}
else {
l = mid + 1;
}
}
cout << ans << endl;
return 0;
}