牛(起点)。)
#include//140ms, 1A#include #include #include using namespace std;int k,c,m;const int inf =0x3f3f3f3f;int a[250][250]; int minmax;int e[20000][3];int head[250]; //链式前向星二维数组表示法,0:to,1:pre,2:wight;void folyd() //最短路不用说{ for(int i=1;i<=k+c;i++) for(int j=1;j<=k+c;j++) for(int ii=1;ii<=k+c;ii++) { if(a[j][ii]>a[j][i]+a[i][ii]) { a[j][ii]=a[j][i]+a[i][ii]; if(a[j][ii]>minmax)minmax=a[j][ii]; //枚举上界 } }}void build(int limit) //由限制,选小于之的路,重新构图{ for(int i=0;i<=k+c+2;i++) head[i]=-1; int num=0; for(int i=c+1;i<=c+k;i++) //超级汇点 { e[num][0]=c+k+1;e[num][1]=head[i];head[i]=num; e[num++][2]=m; e[num][0]=i;e[num][1]=head[c+k+1];head[c+k+1]=num; e[num++][2]=0; } for(int i=1;i<=c;i++) //超级源点 { e[num][0]=0;e[num][1]=head[i];head[i]=num; e[num++][2]=0; e[num][0]=i;e[num][1]=head[0];head[0]=num; e[num++][2]=1; } for(int i=1;i<=k;i++) //其他点 for(int j=k+1;j<=k+c;j++) if(a[i][j]<=limit) { e[num][0]=j-k;e[num][1]=head[i+c];head[i+c]=num; e[num++][2]=0; e[num][0]=i+c;e[num][1]=head[j-k];head[j-k]=num; e[num++][2]=1; }}int level[250];int vis[250];bool bfs() //bfs+dfs,dinic算法{ for(int i=0;i<=k+c+1;i++) vis[i]=level[i]=0; queue q; q.push(0);vis[0]=1; while(!q.empty()) { int cur=q.front();q.pop(); for(int i=head[cur];i!=-1;i=e[i][1]) { int to=e[i][0]; if(!vis[to]&&e[i][2]>0) { vis[to]=1; level[to]=level[cur]+1; if(to==k+c+1)return 1; q.push(to); } } } return vis[k+c+1];}int dfs(int uu,int minf) { if(uu==k+c+1||minf==0)return minf; int sum=0,f; for(int i=head[uu];i!=-1&&minf;i=e[i][1]) { int to=e[i][0]; if(level[to]==level[uu]+1&&e[i][2]>0) { f=dfs(to,minf left+1) //二分答案,注意一下 { mid=(right+left)/2; if(check(mid)) { right=mid; } else left=mid; } if(check(right-1)) //最后二分时判断特殊情况 printf("%d\n",right-1); else printf("%d\n",right);}