二分&01最短路

Telephone Lines

https://vjudge.net/problem/12427/origin

题意:有n个点m条边,每条边为双向且有一个权值,最多可以让k条边的权值变为0,现要最小化从n号点到1号点经过的边权的最大值

思路1:首先设经过的边权的最大值为mid,我们二分这个mid值,mid值大时n到1的路径一定包含mid值小的路径,即满足单调性,所以问题转化为是否存在一种方案使得边权最大值小于等于mid(可以让k条边的边权置0)

我们可以将所有边权大于mid的边长度设置为1,其余的设置为0,这样就可以变为跑01最短路,看最短路长度是否小于等于k(小于等于k时便可以把这些边权大于mid的边的边权置0,即当前mid值满足题意)

01最短路解法:类似用优先队列跑BFS,只不过因为边权只有0和1,这样可以改成用双端队列,如果边权是0就将扩展点加入队首,否则加入队尾,每次拿出队首的点进行扩展,可以保证每次拿出来的都是距离最小的点

#include<iostream>
#include<cstdio>
#include<cstring>
#include<deque>
#define MAXN 1005
#define MAXM 10005
#define INF 0x3f3f3f3f
using namespace std;
int head[MAXN],tot;
struct E
{
	int u,v,w;
}e[MAXM];
struct edge
{
	int v,w,nxt;
}edg[MAXM << 1];
inline void addedg(int u,int v,int w)
{
	edg[tot].v = v;
	edg[tot].w = w;
	edg[tot].nxt = head[u];
	head[u] = tot++;
}
int n,m,k;
bool vis[MAXN];
struct node
{
	int u,w;
	node(){}
	node(int u,int w):u(u),w(w){}
}nod;
deque<node> qu;
inline void init()
{
	memset(head,-1,sizeof(int)*(n+1));
	memset(vis,false,sizeof(bool)*(n+1));
	tot = 0;
	while(!qu.empty())
		qu.pop_front();
}
inline bool check(int x)
{
	init();
	int u,v,w;
	for(int i = 1;i <= m;++i)
	{
		if(e[i].w > x)
			w = 1;
		else
			w = 0;
		addedg(e[i].u,e[i].v,w);
		addedg(e[i].v,e[i].u,w);
	}
	qu.push_front(node(n,0));
	while(!qu.empty())
	{
		nod = qu.front();
		qu.pop_front();
		u = nod.u,w = nod.w;
		if(u == 1)
		{
			if(w <= k)
				return true;
			else
				return false;
		}
		if(vis[u])
			continue;
		vis[u] = 1;
		for(int i = head[u];i != -1;i = edg[i].nxt)
		{
			v = edg[i].v;
			if(!vis[v])
			{
				if(edg[i].w == 0)
					qu.push_front(node(v,w));
				else
					qu.push_back(node(v,w+1));
			}
		}
	}
	return false;
}
int main()
{
	while(~scanf("%d%d%d",&n,&m,&k))
	{
		int l = 0,r = 0,mid,ans = -1;
		for(int i = 1;i <= m;++i)
		{
			scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
			r = max(r,e[i].w);
		}
		while(l <= r)
		{
			mid = (l+r) >> 1;
			if(check(mid))
			{
				ans = mid;
				r = mid-1;
			}
			else
				l = mid+1;
		}
		printf("%d\n",ans);
	}
	return 0;
}

思路二:
https://blog.csdn.net/xing_mo/article/details/103925627

发布了50 篇原创文章 · 获赞 3 · 访问量 3120

猜你喜欢

转载自blog.csdn.net/xing_mo/article/details/103926607