zoukankan      html  css  js  c++  java
  • 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(nlog (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
    ",e[i].x-1,e[i].y-1,e[i].z);
    	return 0;
    }
    

      

  • 相关阅读:
    03 python基础——logging模块
    六、Celery任务执行超时的设置
    python 单例模式线程安全的示例
    Linux samba磁盘的挂载
    Linux 添加新硬盘无法识别[无需重启]的解决方法
    Windows注册表关闭系统服务
    五、Celery 高级用法【20200912】
    四、Celery 路由学习篇
    三、Celery Linux操作系统后台启动的服务制作
    二、Python Celery 4.4.7 与 Django 2.X的集成【定时任务的调用】
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/CF715B.html
Copyright © 2011-2022 走看看