洛谷 P1401 城市

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;
}

猜你喜欢

转载自blog.csdn.net/Dove_xyh/article/details/108352780