一开始以为是费用流。。半天搞不出
经过学弟讲解才知道是这么个问题
先用floyd求出任意两个事物间的最短距离,题目要求在所有牛都能找到机器的前提下,最长距离最小(其实看到这样的字眼就应该想到二分),我们可以二分答案
对于每一个答案建图跑网络流,只建容量小于mid的边,看看是否所有的牛都能找到机器就好
不知道为何用sap模板老是TLE - -||明明感觉比dinic要快啊..
#include"cstdio" #include"queue" #include"cmath" #include"stack" #include"iostream" #include"algorithm" #include"cstring" #include"queue" #include"map" #include"set" #include"vector" #define ll long long #define mems(a,b) memset(a,b,sizeof(a)) using namespace std; const int MAXN = 350; const int MAXE = 20050; const int INF = 0x3f3f3f3f; struct node{ int s,e,next,val; node(){} node(int a,int b,int c,int d):s(a),e(b),next(c),val(d){} }edge[MAXE]; int tot,src,des,m,k,c; int first[MAXN],dep[MAXN],gap[MAXN]; int mat[MAXN][MAXN]; void init(){ tot=0; mems(first,-1); } void addedge(int u,int v,int w){ //cout<<u<<' '<<v<<' '<<w<<endl; edge[tot]=node(u,v,first[u],w); first[u]=tot++; edge[tot]=node(v,u,first[v],0); first[v]=tot++; } bool bfs(int src,int des){ mems(dep,-1); queue<int> q; while(!q.empty()) q.pop(); q.push(src); dep[src]=0; while(!q.empty()){ int cur=q.front();q.pop(); for(int i=first[cur];i!=-1;i=edge[i].next){ int v=edge[i].e; if(dep[v]!=-1||edge[i].val<=0) continue; dep[v]=dep[cur]+1; q.push(v); } } return dep[des]!=-1; } int dfs(int s,int t,int flow){ if(s==t) return flow; int newflow=0; for(int i=first[s];i!=-1;i=edge[i].next){ int v=edge[i].e; int w=edge[i].val; if(dep[v]!=dep[s]+1||!edge[i].val) continue; int temp=dfs(v,t,min(w,flow-newflow)); newflow+=temp; edge[i].val-=temp; edge[i^1].val+=temp; if(newflow==flow) break; } return newflow; } bool dinic(int s,int t,int c){ int sum=0; while(bfs(s,t)){ sum+=dfs(s,t,INF); } return sum==c; } void build(int maxv){ init(); for(int i=1;i<=k;i++) addedge(src,i,m); for(int i=k+1;i<=k+c;i++) addedge(i,des,1); for(int i=1;i<=k;i++) for(int j=k+1;j<=k+c;j++) if(mat[i][j]<=maxv) addedge(i,j,1); } void floyd(int N){ for(int k=1;k<=N;k++) for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) mat[i][j]=min(mat[i][j],mat[i][k]+mat[k][j]); } int main(){ //freopen("in.txt","r",stdin); while(~scanf("%d%d%d",&k,&c,&m)){ for(int i=1;i<=k+c;i++) for(int j=1;j<=k+c;j++){ scanf("%d",&mat[i][j]); if(!mat[i][j]) mat[i][j]=INF; } floyd(k+c); src=0; des=k+c+1; int low=0,high=INF,mid; int ans=INF; while(low<=high){ int mid=(low+high)>>1; build(mid); if(dinic(src,des,c)){ ans=min(ans,mid); high=mid-1; } else low=mid+1; } cout<<ans<<endl; } return 0; }