Solution1:
可由题意得一定存在T条路径,所以我们寻找T遍路径。对于每一次的路径寻找,二分答案此次的最长路段长,若满足条件则标记路径。(对于标记的路径,以后则不能使用)由此,我们可得到,答案即为第T次寻找路径的最长路段长。
时间复杂度:O(T (n+m)logm),且常数较大。
洛谷TLE 7
#include <bits/stdc++.h>
using namespace std;
const int N=205,M=4e4+5;
int n,m,t,u,v,w,tot,l,r,mid,ans,minn;
bool vis[N];
struct number{
int x,y,w;}num[M<<1];
int cnt,head[N];
struct edge{
int next,to,w,f;}e[M<<1];
inline bool cmp(number a,number b)
{
return a.w<b.w;
}
bool dfs(int u,int w)
{
vis[u]=true;
if (u==n) return true;
for (register int i=head[u]; i; i=e[i].next)
if (!e[i].f && !vis[e[i].to] && e[i].w<=w)
{
if (dfs(e[i].to,w))
{
return true;
}
}
return false;
}
bool dfs2(int u,int w)
{
vis[u]=true;
if (u==n) return true;
for (register int i=head[u]; i; i=e[i].next)
if (!e[i].f && !vis[e[i].to] && e[i].w<=w)
{
if (dfs2(e[i].to,w))
{
e[i].f=1;
return true;
}
}
return false;
}
inline bool jay(int mid)
{
for (register int i=1; i<=n; ++i) vis[i]=false;
return dfs(1,num[mid].w);
}
inline void add(int u,int v,int w)
{
cnt++;
e[cnt].next=head[u];
e[cnt].to=v;
e[cnt].w=w;
head[u]=cnt;
}
int main(){
scanf("%d%d%d",&n,&m,&t);
for (register int i=1; i<=m; ++i)
{
scanf("%d%d%d",&u,&v,&w);
tot++; num[tot].x=u; num[tot].y=v; num[tot].w=w;
tot++; num[tot].x=v; num[tot].y=u; num[tot].w=w;
add(u,v,w); add(v,u,w);
}
sort(num+1,num+tot+1,cmp);
while (t--)
{
l=1; r=tot; ans=0;
while (l<=r)
{
mid=l+r>>1;
if (jay(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
for (register int i=1; i<=n; ++i) vis[i]=false;
dfs2(1,num[ans].w);
minn=max(minn,num[ans].w);
}
printf("%d\n",minn);
return 0;
}
Solution2:
枚举最大的边长,对于 长度<=枚举的长度 的边,流量记为1,最大流若大于等于T则满足条件。我们可以想到二分枚举答案,时间复杂度:O(nmlogm)。
Solution3:
如果我们按边长从小到大顺序枚举最大边长,每次只在残余网络上跑最大流,那么,若干次最大流跑下来的总复杂度应该为:O(nm)。
#include <bits/stdc++.h>
using namespace std;
const int N=205,M=4e4+5,inf=2e9;
int n,m,T,tot,s,t;
int b[M],d[N];
int cnt=1,head[N];
struct edge{
int next,to,w;}e[M<<1];
struct number{
int x,y,w;}num[M];
inline bool cmp(number a,number b)
{
return a.w<b.w;
}
inline void add(int u,int v,int w)
{
cnt++;
e[cnt].next=head[u];
e[cnt].to=v;
e[cnt].w=w;
head[u]=cnt;
}
inline void insert(int u,int v)
{
add(u,v,1); add(v,u,1);
}
queue<int>q;
inline bool bfs()
{
memset(d,-1,sizeof(d));
d[s]=0;
q.push(s);
while (q.size())
{
int u=q.front(); q.pop();
for (register int i=head[u]; i; i=e[i].next)
{
if (e[i].w && d[e[i].to]==-1)
{
d[e[i].to]=d[u]+1;
q.push(e[i].to);
}
}
}
if (d[t]==-1) return false;
return true;
}
inline int dfs(int u,int flow)
{
if (u==t) return flow;
int last=flow;
for (register int i=head[u]; i; i=e[i].next)
{
if (e[i].w && d[e[i].to]==d[u]+1)
{
int k=dfs(e[i].to,min(e[i].w,last));
if (!k) {
d[e[i].to]=-1; continue;}
last-=k; e[i].w-=k; e[i^1].w+=k;
}
if (!last) break;
}
return flow-last;
}
inline int dinic()
{
int ans=0;
while (bfs()) ans+=dfs(s,inf);
return ans;
}
int main(){
scanf("%d%d%d",&n,&m,&T);
for (register int i=1; i<=m; ++i)
scanf("%d%d%d",&num[i].x,&num[i].y,&num[i].w),b[i]=num[i].w;
sort(b+1,b+m+1);
tot=unique(b+1,b+m+1)-b-1;
sort(num+1,num+m+1,cmp);
int j=1;
s=1; t=n;
for (register int i=1; i<=tot; ++i)
{
while (j<=m && num[j].w<=b[i])
{
insert(num[j].x,num[j].y);
j++;
}
T-=dinic();
if (T<=0)
{
printf("%d\n",b[i]);
return 0;
}
}
return 0;
}