poj2391 Ombrophobic Bovines 拆点连边要注意
【题意】:给定F个牛棚和P条路径,每条路径有一个长度,现在每个牛棚有一定的容量和牛数,因为牛棚牛数可能大于容量,所以要牛棚之间的牛要进行相互地移动,每移动一个距离就花费一单位的时间,求从开始移动到每头牛都移动到牛棚的最小时间。
一开始自己建图建错了,把每个点i拆成i'和i'',若i-->j有边 就i''连j'容量INF。再就是源点连每个i‘容量为INF,i’连i''容量为牛数,j'连j''容量为牛棚容量,j''连汇点容量为INF。
但是自己忽略了一点 若1->2->3,这是一条链,而1->2最短路为1,2->3为1,1->3为 2,此时如果我们限制最大距离为1的话,建的新图中必然有1->2,2->3, 新图中1和3也会间接的连接起来,而我们显然是不想这么让它流的。如果i->j这条边符合了距离限制,就加i'->j'' ,比如1->2->3这个例子,加的边是1’->2'',2'->3'' 不会有流从1流到3去,因为加的每条边都流向了汇点。 见(http://blog.csdn.net/sdj222555/article/details/7771553)
此为TLE代码,先放这里
1 #include<iostream> 2 #include<vector> 3 #include<string.h> 4 #include<queue> 5 #include<cstdio> 6 using namespace std; 7 #define INF 10000000 8 #define maxn 820 9 10 struct E{int from;int to;int c;int f;}; 11 vector <int> g[maxn]; 12 vector<E> edge; 13 int d[maxn],vis[maxn],cur[maxn],num[maxn],p[220],n,tot; 14 15 int dis[202][202],nz[202],you[202]; 16 17 18 void add(int from,int to,int c) 19 { 20 E temp1,temp2; 21 temp1.from =from; temp1.to=to; temp1.c=c;temp1.f=0; 22 temp2.from =to; temp2.to=from; temp2.c=0;temp2.f=0; 23 edge.push_back (temp1); 24 edge.push_back (temp2); 25 int m=edge.size (); 26 g[from].push_back (m-2); 27 g[to].push_back (m-1); 28 } 29 30 void bfs(int s,int t) 31 { 32 int i; 33 queue<int > q; 34 q.push (t); 35 d[t]=0; 36 memset(vis,0,sizeof(vis)); 37 vis[t]=1; 38 while(!q.empty ()) 39 { 40 int t=q.front ();q.pop (); 41 for(i=0;i<g[t].size ();i++) 42 { 43 E e;e=edge[g[t][i]]; 44 if(!vis[e.to]) 45 { 46 q.push (e.to); 47 vis[e.to]=1; 48 d[e.to]=d[t]+1; 49 } 50 } 51 } 52 } 53 54 int zg(int s,int t) 55 { 56 int x=t,a=INF; 57 while(x!=s) 58 { 59 //printf("x %d\n",x); 60 E e=edge[p[x]]; 61 if(a>e.c-e.f) 62 a=e.c-e.f; 63 x=e.from; 64 } 65 x=t; 66 while(x!=s) 67 { 68 edge[p[x]].f+=a; 69 edge[p[x]^1].f-=a; 70 x=edge[p[x]].from ; 71 } 72 return a; 73 } 74 75 int maxflow(int s,int t,int n) 76 { 77 int flow=0,i; 78 bfs(s,t); 79 memset(num,0,sizeof(num)); 80 memset(cur,0,sizeof(cur)); 81 for(i=0;i<=t;i++) 82 num[d[i]]++; 83 int x=s; 84 while(d[s]<=n) 85 { 86 //printf("temp %d\n",flow); 87 if(x==t) 88 { 89 flow+=zg(s,t); 90 x=s; 91 //printf("flow %d\n",flow); 92 } 93 int ok=0; 94 for(i=cur[x];i<g[x].size ();i++) 95 { 96 E e; 97 e=edge[g[x][i]]; 98 if(e.c>e.f&&d[x]==d[e.to]+1) 99 { 100 ok=1; 101 102 p[e.to]=g[x][i]; 103 104 cur[x]=i; 105 x=e.to;//!@#$%^& 106 break; 107 } 108 } 109 if(ok==0) 110 { 111 int m=n; 112 for(i=0;i<g[x].size ();i++) 113 { 114 E e; 115 e=edge[g[x][i]]; 116 if(e.c>e.f&&m>d[e.to]) 117 m=d[e.to]; 118 } 119 if(--num[d[x]]==0) break; 120 num[d[x]=m+1]++; 121 cur[x]=0;////!@#$%^^& 122 if(x!=s) 123 x=edge[p[x]].from ; 124 125 } 126 } 127 return flow; 128 } 129 130 bool ok(int x) 131 { 132 edge.clear(); 133 for(int i=0;i<=3*n+1;i++) 134 g[i].clear(); 135 136 for(int i=1;i<=n;i++) 137 { 138 add(0,i,INF); 139 add(i,i+n,you[i]); 140 add(i+2*n,i+3*n,nz[i]); 141 add(i+3*n,4*n+1,INF); 142 143 for(int j=1;j<=n;j++) 144 if(dis[i][j]<=x) 145 { 146 add(i,j+3*n,INF); 147 add(3*j+n,i,INF); 148 } 149 } 150 int flow; 151 flow=maxflow(0,4*n+1,4*n+1); 152 //printf("flow %d x %d\n",flow,x); 153 if(flow==tot) 154 return true; 155 return false; 156 } 157 158 int solve(int maxe) 159 { 160 int left=0,right=maxe,ans=maxe; 161 while(left<=right) 162 { 163 int mid=(left+right)/2; 164 if(ok(mid)) 165 { 166 ans=min(ans,mid); 167 right=mid-1; 168 } 169 else left=mid+1; 170 } 171 return ans; 172 } 173 174 int main() 175 { 176 int m,a,b,c; 177 while(~scanf("%d%d",&n,&m)) 178 { 179 tot=0; 180 for(int i=1;i<=n;i++) 181 { 182 scanf("%d%d",&you[i],&nz[i]); 183 tot+=you[i]; 184 } 185 for(int i=1;i<=n;i++) 186 for(int j=1;j<=n;j++) 187 if(i==j) 188 dis[i][j]=0; 189 else 190 dis[i][j]=INF; 191 int size1=0; 192 while(m--) 193 { 194 scanf("%d%d%d",&a,&b,&c); 195 dis[a][b]=min(dis[a][b],c); 196 dis[b][a]=min(dis[b][a],c); 197 } 198 int maxe=0; 199 for(int k=1;k<=n;k++) 200 for(int i=1;i<=n;i++) 201 for(int j=1;j<=n;j++) 202 { 203 dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]); 204 if(k==n) 205 maxe=max(maxe,dis[i][j]); 206 } 207 printf("%d\n",solve(maxe)); 208 } 209 return 0; 210 }