Codeforces 715B. Complete The Graph 最短路,Dijkstra,构造

原文链接https://www.cnblogs.com/zhouzhendong/p/CF715B.html

题解

接下来说的“边”都指代“边权未知的边”。

将所有边都设为 L+1,如果dis(S,T) < L ,那么必然无解。

将所有边都设为 1 ,如果 dis(S,T) > L ,那么必然无解。

考虑将任意一条边的权值+1,则 dis(S,T) 会 +0 或者 +1 。

如果将所有边按照某一个顺序不断+1,直到所有边的权值都是L+1了,那么在这个过程中,dis(S,T) 是递增的,而且一定在某一个时刻 dis(S,T) = L。

这样的话我们就可以二分答案+dijkstra解决这个问题了。

时间复杂度 $O(n\log (n+m) \log (mL))$ 。

事实上有更优秀的做法(我并没有想到),懒得写了,给个链接:

https://blog.csdn.net/aufeas/article/details/52916704

代码

#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
using namespace std;
typedef long long LL;
#define pii pair <int,int>
LL read(){
	LL x=0,f=0;
	char ch=getchar();
	while (!isdigit(ch))
		f|=ch==‘-‘,ch=getchar();
	while (isdigit(ch))
		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return f?-x:x;
}
const int N=1005,M=10005,INF=1e9+5;
int n,m,L,S,T;
struct Edge{
	int x,y,z;
}e[M];
struct Graph{
	int cnt,y[M*2],z[M*2],nxt[M*2],fst[N];
	void clear(){
		cnt=1,clr(fst);
	}
	void add(int a,int b,int c){
		y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt,z[cnt]=c;
	}
	void update(int id,int v){
		z[id<<1]=z[id<<1|1]=v;
	}
}g;
vector <int> eid;
int dis[N],vis[N];
int Dijkstra(){
	static priority_queue <pii,vector <pii>,greater <pii> > Q;
	while (!Q.empty())
		Q.pop();
	for (int i=1;i<=n;i++)
		dis[i]=INF,vis[i]=0;
	dis[S]=0;
	Q.push(make_pair(dis[S],S));
	while (!Q.empty()){
		pii p=Q.top();
		Q.pop();
		int x=p.second;
		if (vis[x]||dis[x]!=p.first)
			continue;
		vis[x]=1;
		for (int i=g.fst[x];i;i=g.nxt[i]){
			int y=g.y[i],z=g.z[i];
			if (!vis[y]&&dis[x]+z<dis[y]){
				dis[y]=dis[x]+z;
				Q.push(make_pair(dis[y],y));
			}
		}
	}
	return dis[T];
}
int check(LL v){
	for (auto i : eid){
		LL d=min(v,(LL)L);
		g.update(i,d+1);
		v-=d;
	}
	return Dijkstra()<=L;
}
int main(){
	n=read(),m=read(),L=read(),S=read()+1,T=read()+1;
	g.clear();
	for (int i=1;i<=m;i++){
		int x=read()+1,y=read()+1,z=read();
		e[i].x=x,e[i].y=y,e[i].z=z;
		g.add(x,y,z);
		g.add(y,x,z);
		if (!z)
			eid.push_back(i);
	}
	for (auto i : eid)
		g.update(i,INF);
	if (Dijkstra()<L)
		return puts("NO"),0;
	for (auto i : eid)
		g.update(i,1);
	if (Dijkstra()>L)
		return puts("NO"),0;
	LL l=0,r=(LL)L*(int)eid.size(),mid,ans=l;
	while (l<=r){
		mid=(l+r)>>1;
		if (check(mid))
			l=mid+1,ans=mid;
		else
			r=mid-1;
	}
	for (auto i : eid){
		LL d=min(ans,(LL)L);
		e[i].z=d+1;
		ans-=d;
	}
	puts("YES");
	for (int i=1;i<=m;i++)
		printf("%d %d %d\n",e[i].x-1,e[i].y-1,e[i].z);
	return 0;
}

  

原文地址:https://www.cnblogs.com/zhouzhendong/p/CF715B.html

时间: 2024-10-11 21:15:08

Codeforces 715B. Complete The Graph 最短路,Dijkstra,构造的相关文章

Codeforces 716D - Complete The Graph(最短路)

题意:给定n个点,m条边,以及起点s,终点t,问你图中是否存在s->t的最短路为L,其中权值为0的可以任意修改. 思路:对给定的边分为2类,权重不为0的直接扔进去建图,权重为0的边先存起来.接着跑一遍堆优化的dij,如果dis[t]小于L,那么无论怎么修改权重0的边都没有办法凑出最短路L: 如果dis[t]=L,那么直接输出:如果dis[t]>L,则将原来事先存起来的边一条一条的加进去,权值设为1.每加一条边就跑一次dij,一旦找到dis[t]<=L,就可以终止并输出. PS:原来堆优化

715B Complete The Graph

传送门 题目大意 给出一个图,一些边带权,另一些边等待你赋权(最小赋为1).请你找到一种赋权方式,使得 s 到 t 的最短路为 L n ≤ 1e3 ,m ≤ 1e4 ,L ≤ 1e9 分析 二分所有边的边权和 使得二分后第p条边权值为k,1~p-1条边权值为inf,剩余边权值为1 对于每种情况跑一次最短路 如果结果小于L则增大点权和否则减少 代码 #include<iostream> #include<cstdio> #include<cstring> #include

POJ 3013 Big Christmas Tree(最短路Dijkstra+优先队列优化,SPFA)

POJ 3013 Big Christmas Tree(最短路Dijkstra+优先队列优化,SPFA) ACM 题目地址:POJ 3013 题意: 圣诞树是由n个节点和e个边构成的,点编号1-n,树根为编号1,选择一些边,使得所有节点构成一棵树,选择边的代价是(子孙的点的重量)×(这条边的价值).求代价最小多少. 分析: 单看每个点被计算过的代价,很明显就是从根到节点的边的价值.所以这是个简单的单源最短路问题. 不过坑点还是很多的. 点的数量高达5w个,用矩阵存不行,只能用边存. 还有路径和结

POJ1062 Expensive dowry 【最短路dijkstra】

详细看:http://blog.csdn.net/lyy289065406/article/details/6645852 简单说一下:每个物品是一个结点,边的权值是,edge[u][v]的值表示用物品u换物品v的价格 一开始所有物品都置为原价,即所有dist[i]为原价,用dijkstra算法,算出0点(啥物品都没有)到各点的最短距离,求出dist[1]即为花费 枚举每个物品的等级为这条交易链的最高等级,把所有等级高于它的或者比它小超过等级限制的点都剔除,可以用bool数组剔除,然后用上述的d

POJ 2387 Til the Cows Come Home (最短路+Dijkstra)

Til the Cows Come Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 29550   Accepted: 9935 Description Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before Farmer John wakes her for the

POJ-3268-最短路(dijkstra算法)

Silver Cow Party Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 12494   Accepted: 5568 Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤ X

hdu 2544 最短路 Dijkstra

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 题目分析:比较简单的最短路算法应用.题目告知起点与终点的位置,以及各路口之间路径到达所需的时间,要求输出起点到终点的最短时间. /* 最短路 Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 35043 Accepted Submission

最短路Dijkstra和Flyod

Problem Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据.每组数据第一行是两个整数N.M(N<=100,M& lt;=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路.N=M=0表 示输入结束.接下来

uva 10801 - Lift Hopping(最短路Dijkstra)

1 /* 2 题目大意: 3 就是一幢大厦中有0-99的楼层, 然后有1-5个电梯!每个电梯有一定的上升或下降速度和楼层的停止的位置! 4 问从第0层楼到第k层最少经过多长时间到达! 5 6 思路:明显的Dijkstra ,在建图的时候u->v可能有多个电梯到达,取时间最少的当作路径的权值! 7 如果我们发现 d[i] > d[j] + map[j][i] + 60, 那么说明从第0层到达第 i 层的时间大于从第j层 8 转移到其他电梯然后到达第 i 层的时间,那么就更新d[i]的值! 9 1