BZOJ1738: [Usaco2005 mar]Ombrophobic Bovines 发抖的牛

n<=200个点m<=1500条无向带权边的图,每个点有人和容量,人可以移动,代价为所有人走过的边的权和,求使所有点人不超过容量的最小代价。

方法一:费用流。

错误!答案与边权不成比例。

方法二:二分一个答案,然后根据floyd求出的最短路看每个点在二分的答案下能去到哪些点,跑最大流检查是否合法。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<algorithm>
  5 //#include<iostream>
  6 using namespace std;
  7 
  8 int n,m;
  9 #define maxn 411
 10 #define maxm 100011
 11 #define LL long long
 12 int a[maxn],b[maxn],sum=0;
 13 LL mp[maxn][maxn];
 14 const LL inf=1e15;
 15 struct Edge{int from,to,next,cap,flow;};
 16 struct Network
 17 {
 18     Edge edge[maxm];int n,s,t,le;
 19     int first[maxn],dis[maxn],cur[maxn];
 20     void clear(int n)
 21     {
 22         memset(first,0,sizeof(first));
 23         le=2;this->n=n;
 24     }
 25     void add_edge(int x,int y,int v)
 26     {
 27         Edge &e=edge[le];
 28         e.to=y;e.from=x;
 29         e.cap=v;e.flow=0;
 30         e.next=first[x];
 31         first[x]=le++;
 32     }
 33     void insert(int x,int y,int v)
 34     {
 35         add_edge(x,y,v);
 36         add_edge(y,x,0);
 37     }
 38     int que[maxn],head,tail;
 39     bool bfs()
 40     {
 41         memset(dis,0,sizeof(dis));
 42         dis[s]=1;
 43         que[head=(tail=1)-1]=s;
 44         while (head!=tail)
 45         {
 46             const int x=que[head++];
 47             for (int i=first[x];i;i=edge[i].next)
 48             {
 49                 Edge &e=edge[i];
 50                 if (e.cap>e.flow && !dis[e.to])
 51                 {
 52                     dis[e.to]=dis[x]+1;
 53                     que[tail++]=e.to;
 54                 }
 55             }
 56         }
 57         return dis[t];
 58     }
 59     int dfs(int x,int a)
 60     {
 61         if (x==t || !a) return a;
 62         int flow=0,f;
 63         for (int &i=cur[x];i;i=edge[i].next)
 64         {
 65             Edge &e=edge[i];
 66             if (dis[e.to]==dis[x]+1 && (f=dfs(e.to,min(a,e.cap-e.flow)))>0)
 67             {
 68                 flow+=f;
 69                 a-=f;
 70                 e.flow+=f;
 71                 edge[i^1].flow-=f;
 72                 if (!a) break;
 73             }
 74         }
 75         return flow;
 76     }
 77     int Dinic(int s,int t)
 78     {
 79         this->s=s;this->t=t;
 80         int ans=0;
 81         while (bfs())
 82         {
 83             for (int i=1;i<=n;i++) cur[i]=first[i];
 84             ans+=dfs(s,0x3f3f3f3f);
 85         }
 86         return ans;
 87     }
 88 }g;
 89 bool check(LL x)
 90 {
 91     g.clear(n*2+2);
 92     int s=g.n-1,t=g.n;
 93     for (int i=1;i<=n;i++)
 94     {
 95         g.insert(s,i,a[i]);
 96         g.insert(i+n,t,b[i]);
 97     }
 98     for (int i=1;i<=n;i++)
 99         for (int j=1;j<=n;j++)
100             if (mp[i][j]<=x) g.insert(i,j+n,0x3f3f3f3f);
101     return g.Dinic(s,t)==sum;
102 }
103 int x,y,v;
104 int main()
105 {
106     scanf("%d%d",&n,&m);
107     for (int i=1;i<=n;i++)
108         scanf("%d%d",&a[i],&b[i]),sum+=a[i];
109     for (int i=1;i<=n;i++)
110         for (int j=1;j<=n;j++)
111             mp[i][j]=inf;
112     for (int i=1;i<=n;i++) mp[i][i]=0;
113     for (int i=1;i<=m;i++)
114     {
115         scanf("%d%d%d",&x,&y,&v);
116         mp[x][y]=min(mp[x][y],(LL)v);
117         mp[y][x]=min(mp[y][x],(LL)v);
118     }
119     for (int k=1;k<=n;k++)
120         for (int i=1;i<=n;i++)
121             for (int j=1;j<=n;j++)
122                 if (mp[i][j]>mp[i][k]+mp[k][j])
123                     mp[i][j]=mp[i][k]+mp[k][j];
124     LL L=0,R=1e15;
125     while (L<R)
126     {
127         const LL mid=(L+R)>>1;
128         if (check(mid)) R=mid;
129         else L=mid+1;
130     }
131     printf(R==1e15?"-1\n":"%lld\n",L);
132     return 0;
133 }
View Code

 

posted @ 2017-09-14 19:10  Blue233333  阅读(236)  评论(0编辑  收藏  举报