[bzoj1738]发抖的牛

二分答案,每一头牛向所有在规定时间内能走到的牛棚连inf的边,每一个源点向牛连牛数量的边,每一个牛棚向汇点连牛棚容量的边,能满流则意味着这个答案可行,否则不可行。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 505
 4 #define ll long long
 5 #define inf 0x3f3f3f3f
 6 struct ji{
 7     int nex,to,len;
 8 }e[N*N],edge[N*N];
 9 queue<int>q;
10 int E,EE,n,m,x,y,z,s,a[N],d[N],head[N],work[N];
11 ll f[N][N];
12 void add(int x,int y,int z){
13     edge[E].nex=head[x];
14     edge[E].to=y;
15     edge[E].len=z;
16     head[x]=E++;
17     if (E&1)add(y,x,0); 
18 }
19 bool bfs(){
20     q.push(0);
21     memset(d,-1,sizeof(d));
22     d[0]=0;
23     while (!q.empty()){
24         int k=q.front();
25         q.pop();
26         for(int i=head[k];i!=-1;i=edge[i].nex)
27             if ((edge[i].len)&&(d[edge[i].to]<0)){
28                 d[edge[i].to]=d[k]+1;
29                 q.push(edge[i].to);
30             }
31     }
32     return d[n]>=0;
33 }
34 int dfs(int k,int s){
35     if (k==n)return s;
36     int p;
37     for(int &i=work[k];i!=-1;i=edge[i].nex)
38         if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){
39             p=dfs(edge[i].to,min(s,edge[i].len));
40             if (p){
41                 edge[i].len-=p;
42                 edge[i^1].len+=p;
43                 return p;
44             }
45         }
46     return 0;
47 }
48 int dinic(){
49     int k,ans=0;
50     while (bfs()){
51         memcpy(work,head,sizeof(work));
52         while (k=dfs(0,inf))ans+=k;
53     }
54     return ans;
55 }
56 bool pd(ll k){
57     for(int i=1;i<=n/2;i++)
58         for(int j=1;j<=n/2;j++)
59             if (f[i][j]<=k)add(i,j+n/2,inf);
60     int t=dinic();
61     memcpy(head,a,sizeof(a));
62     memcpy(edge,e,sizeof(e));
63     E=EE;
64     return t==s;
65 }
66 int main(){
67     scanf("%d%d",&n,&m);
68     memset(head,-1,sizeof(head));
69     for(int i=1;i<=n;i++){
70         scanf("%d%d",&x,&y);
71         add(0,i,y);
72         add(n+i,2*n+1,x);
73         s+=x;
74     }
75     memset(f,inf,sizeof(f));
76     for(int i=1;i<=n;i++)f[i][i]=0;
77     for(int i=1;i<=m;i++){
78         scanf("%d%d%d",&x,&y,&z);
79         f[x][y]=f[y][x]=min(f[x][y],1LL*z);
80     }
81     for(int i=1;i<=n;i++)
82         for(int j=1;j<=n;j++)
83             for(int k=1;k<=n;k++)
84                 f[j][k]=min(f[j][k],f[j][i]+f[i][k]);
85     n=n*2+1;
86     ll l=0,r=2e11;
87     memcpy(a,head,sizeof(a));
88     memcpy(e,edge,sizeof(e));
89     EE=E;
90     while (l<r){
91         ll mid=(l+r>>1);
92         if (pd(mid))r=mid;
93         else l=mid+1;
94     }
95     if (l==2e11)l=-1;
96     printf("%lld",l);
97 }
View Code

 

posted @ 2019-07-28 10:42  PYWBKTDA  阅读(115)  评论(0编辑  收藏  举报