題意:給定一張無向圖,有n個節點p條邊,
要求在圖中從1到n找到t條路徑,並且使這t條路徑中的最長邊最小,
輸出這個最小的最長邊
思路:讓所有的邊值為1,即可知道從s到t有多少條路,二分處理最大值的最小值即可。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=300;const int maxm=50000;const int inf=0x3f3f3f3f;int head[maxm],cnt=0;int n,m;struct nodee{ int u,v,w;}aa[maxm*4+100];struct edge{ int v,nxt,w;}edge[maxm*4+100];void add_edge(int u,int v,int w){ edge[cnt].v=v; edge[cnt].w=w; edge[cnt].nxt=head[u]; head[u]=cnt++;}int numh[maxn],h[maxn],curedge[maxn],pre[maxn];int sap(int s,int t){ memset(numh,0,sizeof(numh)); memset(h,0,sizeof(h)); memset(pre,-1,sizeof(pre)); int cur_flow,flow_ans=0,u,tmp,neck,i; for(i=1;i<=n;i++) { curedge[i]=head[i]; } numh[0]=n; u=s; while(h[s]<n) { if(u==t) { cur_flow=inf; for(i=s;i!=t;i=edge[curedge[i]].v) { if(cur_flow>edge[curedge[i]].w) { neck=i; cur_flow=edge[curedge[i]].w; } } for(i=s;i!=t;i=edge[curedge[i]].v) { tmp=curedge[i]; edge[tmp].w-=cur_flow; edge[tmp^1].w+=cur_flow; } flow_ans+=cur_flow; u=neck; } for(i=curedge[u];i!=-1;i=edge[i].nxt) { if(edge[i].w&&h[u]==h[edge[i].v]+1) { break; } } if(i!=-1) { curedge[u]=i; pre[edge[i].v]=u; u=edge[i].v; } else { if(0==--numh[h[u]]) break; curedge[u]=head[u]; for(tmp=n,i=head[u];i!=-1;i=edge[i].nxt) { if(edge[i].w) { tmp=min(tmp,h[edge[i].v]); } } h[u]=tmp+1; ++numh[h[u]]; if(u!=s) u=pre[u]; } } return flow_ans;}int main (){ int t; scanf("%d%d%d",&n,&m,&t); memset(head,-1,sizeof(head)); cnt=0; int maxx=0; for(int i=1;i<=m;i++) { scanf("%d%d%d",&aa[i].u,&aa[i].v,&aa[i].w); maxx=max(maxx,aa[i].w); } int l=0,r=maxx; int answer=maxx; while(l<=r) { int mid=(l+r)/2; memset(head,-1,sizeof(head)); cnt=0; for(int i=1;i<=m;i++) { if(aa[i].w<=mid) { add_edge(aa[i].u,aa[i].v,1); add_edge(aa[i].v,aa[i].u,1); } } int anss=sap(1,n); //printf("%d %d\n",anss,mid); if(anss>=t) { r=mid-1; answer=min(answer,mid); } else { l=mid+1; } } printf("%d\n",answer);}