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 ":"%lld ",L); 132 return 0; 133 }