- 难点在建图
- 建分层图,拆点,从一层走到另一层代表当前走的路径长度增加了1
- 二分答案,代表最短路最大是多少
- 从起点开始求一个最小割
- 把属于最小割的边ban掉,就相当于选中了这个点,及花费增加1,只有这样才能使最短路增加1
- 画个图感性理解一下
- 思路太神仙了,这题就当板子用吧
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define S(i,j) (j+(i-1)*2*n)
#define T(i,j) (j+(i-1)*2*n+n)
using namespace std;
const int oo=1e9;
const int N=1e5;
struct node{int y,n,v;}e[N*50];
struct Q{int x,y;}a[N];
int s,t,n,m,k,l,r,mid,ans=0,len=1,d[N],lin[N];
void read(int x,int y,int v)
{e[++len].y=y,e[len].v=v,e[len].n=lin[x],lin[x]=len;}
void add(int x,int y,int v)
{read(x,y,v),read(y,x,0);}
bool bfs(int s){
queue<int> q;
memset(d,0,sizeof(d));
q.push(s),d[s]=1;
while(q.size()){
int x=q.front();q.pop();
for(int i=lin[x];i;i=e[i].n){
int y=e[i].y;
if(d[y]||e[i].v==0)continue;
d[y]=d[x]+1;
q.push(y);
}
}return d[t]>0;
}
int dfs(int x,int minf){
int sum=0,flow=0;
if(x==t)return minf;
for(int i=lin[x];i;i=e[i].n){
int y=e[i].y;
if(d[y]==d[x]+1&&e[i].v){
flow=dfs(y,min(minf,e[i].v));
if(!flow)d[y]=0;
sum+=flow,minf-=flow,e[i].v-=flow,e[i^1].v+=flow;
if(!minf)return sum;
}
}return sum;
}
void init(){
memset(lin,0,sizeof(lin));
len=1;
}
bool judge(int mid){
init();
rep(i,1,mid+1){
rep(j,2,n-1)add(S(i,j),T(i,j),1);
if(i!=mid+1){
add(S(i,n),S(i+1,n),oo);
rep(j,2,n-1)add(S(i,j),T(i+1,j),oo);
rep(j,1,m){
add(T(i,a[j].y),S(i+1,a[j].x),oo);
add(T(i,a[j].x),S(i+1,a[j].y),oo);
}
}
}
s=T(1,1),t=S(mid+1,n);
int ans=0;
while(bfs(s)){
ans+=dfs(s,oo);
if(ans>k)return 0;
}
return ans<=k;
}
int main()
{
freopen("min.in","r",stdin);
freopen("min.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
rep(i,1,m){
scanf("%d%d",&a[i].x,&a[i].y);
a[i].x++,a[i].y++;
}
l=0,r=2*n;
while(l<=r){
mid=l+r>>1;
if(judge(mid))ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans+1);
return 0;
}