首页 > 其他分享 >0712最短路选写

0712最短路选写

时间:2023-07-15 15:55:53浏览次数:31  
标签:选写 int 短路 vis 0712 dis 考虑 lld

[CF1842D] Tenzing and His Animal Friends

Description

Tenzing 有 \(n\) 个朋友,每次举办聚会可以邀请一些朋友,有如下限制:

  • \(1\) 必须参加,\(n\) 不能参加。

  • 有 \(m\) 条限制 \((u, v, w)\),表示 \(u\) 和 \(v\) 中只有一个在聚会中的总时间不超过 \(w\)。

最大化聚会总时间,并给出相应方案,即给出总聚会时间,每次聚会给出参与聚会的人和单次聚会时长。

Solution

我们考虑建图做法,首先我们可以把限制 \((u, v, w)\) 建边,而后我们考虑因为 \(n\) 不能参加聚会,所以 $u\to n $ 也有相应限制,我们考虑类似从 \(n\) 开始扩散的做法,即 \(u\) 在 \(w\) 时刻前必须从 \(n\) 走到 \(u\),因而这样向前推可以得任何点必须在他的父节点等待 \(w_i\) 时刻前被到达,因而对于整张图考虑即相应总聚会时间最大值为 \(1\to n\) 的最短路。考虑将 \(n\) 作为起点用迪杰斯特拉算法跑最短路。不合法状态即 \(1\to n\) 最短路为极大值。

而后我们考虑构造,对于任何一个点 \(i\) 他的状态取决于当前的 \(dis_i\) 是否大于 0,大于 0 则状态为 1,反之为 0。我们考虑枚举一个时刻 \(T\) 的 \(T'=\min ({dis_k},k\in{u})\),则在从当前时刻过渡到这个时刻所有点的 \(dis\) 均被去掉 \(T\),因而将这个时刻和所有点的状态存进 vector 中维护即可。当 \(dis_1\) 为 0 时结束更新答案。

Code

#include<bits/stdc++.h>
using namespace std;

#define int long long
const int inf=4557430888798830398;
const int N=5e5+7;
vector<pair<int,int> > G[N];
int dis[N<<2];
bool _vis[N<<2];
int n,m,k;
int a[N];
//const int inf=1e9;

struct node{
	int dis,id;
	friend bool operator < (node a,node b){
		return a.dis>b.dis;
	}
};

void Dj(int s){
	memset(_vis,0,sizeof _vis);
	priority_queue<node> q;
	memset(dis,0x3f,sizeof dis);
	dis[s]=0;
  q.push({0,s});
	while(!q.empty()){
		int u=q.top().id;
		q.pop();
		if(_vis[u]) continue;
		_vis[u]=1;
		for(auto i:G[u]){
			int k=i.first,w=i.second;
			if(dis[k]>dis[u]+w){
				dis[k]=dis[u]+w;
				q.push({dis[k],k});
			}
		}
	}
}

struct node2 {
    int sta[110],t;
};

vector<node2> ans;

signed main(){
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=m;i++){
		int u,v,w;scanf("%lld%lld%lld",&u,&v,&w);
		G[u].push_back(make_pair(v,w)),G[v].push_back(make_pair(u,w));
	}
	Dj(n);
	if(dis[1]>=inf) return printf("inf"),0;
	printf("%lld ",dis[1]);
  while(dis[1]!=0){
	  int _min=inf;
		for(int i=1;i<=n;i++) if(dis[i]>0&&dis[i]<_min) _min=dis[i];
		node2 a;
		for(int i=1;i<=n;i++) a.sta[i]=dis[i]>0;
		a.t=_min;
		ans.push_back(a);
		for(int i=1;i<=n;i++) dis[i]-=_min;
	}
	printf("%lld\n",ans.size());
	for(auto it:ans){
	  for(int i=1;i<=n;i++){
			printf("%lld",it.sta[i]);
		}
	  printf(" %lld\n",it.t); 
	}
  return 0;
}

[CF715B] Complete The Graph

Description

给 \(n\) 点 \(m\) 边,要求你修改 \(m\) 条边中边权为 \(0\) 的边, 使满足 \(S\to T\) 的最短路长度是 \(L\),且输出答案的时候边为 \(0\) 的边的权值必须在 \([1,1\times 10^{18}]\) 内。

Solution

我们考虑一个暴力做法,即首先我们把边权不为 \(0\) 的边的编号存进一个 vector 内,考虑仅在图中存边权不为 \(0\) 的边。而后我们跑 \(S\to T\) 的最短路极为 \(dis_t\),我们考虑加边对这样一个 \(dis_t\) 的影响,即只会使得 \(dis_t\) 变小或不变。而后我们考虑若 \(dis_t<L\) 则显然不合法输出 NO,若 \(dis_t=L\) 则我们不希望边权为 \(0\) 的边对这张已经合法的图有任何影响,则所有边权为 \(0\) 的边权值改为极大值即可。

而后我们考虑 \(dis_t>L\) 的情况。首先,若最短路变化了那么证明从 \(S\) 到 \(T\) 的最短路经过该边,于是我们可以通过以下方式来使得最短路恰好等于 \(L\)。

而后我们考虑不断枚举边权为 \(0\) 的并且把其边权设为 \(1\) 并加入图中,这样可以使得最短路尽可能短(此时尽可能短直到 \(dis_t<L\) 时考虑修改权值,并不代表一直使最短路尽可能短,换言之这样的策略是找到一条关键边使得 \(S\) 到 \(T\) 的最短路恰好满足情况),那么我们考虑对于每次枚举跑一次最短路,若此时 \(dis_t<L\),那么显然这种情况是不合法的,我们考虑把它补到 \(L-dis_t\)。此时恰好使得当前图合法,因而其他没枚举到的边不需要不能影响该图的最短路,因而和上面一样赋值为极大值即可。

这种贪心的思路足够通过本题。

Code

#include<bits/stdc++.h>
using namespace std;

#define int long long
const int N=5e4+7;
vector<pair<int,int> > G[N];
vector<int> vec;
int dis[N<<2];
bool _vis[N<<2];
int n,m;
int u[N],v[N],w[N];
const int inf=1e18;
int p,l,s,t;

struct node{
	int dis,id;
	friend bool operator < (node a,node b){
		return a.dis>b.dis;
	}
};

void Dj(int s){
	memset(_vis,0,sizeof _vis);
	priority_queue<node> q;
	memset(dis,0x3f,sizeof dis);
	dis[s]=0;
	q.push({0,s});
	while(!q.empty()){
		int u=q.top().id;
		q.pop();
		if(_vis[u]) continue;
		_vis[u]=1;
		for(auto i:G[u]){
			int k=i.first,w=i.second;
			if(dis[k]>dis[u]+w){
				dis[k]=dis[u]+w;
				q.push({dis[k],k});
			}
		}
	}
}

void print()
{
	puts("YES");
	for(int i=1;i<=m;i++){
		if(!w[i]){
			if(i<p)
			printf("%lld %lld %lld\n",u[i],v[i],1ll);
			if(i==p)
			printf("%lld %lld %lld\n",u[i],v[i],l-dis[t]+1);
			if(i>p)
			printf("%lld %lld %lld\n",u[i],v[i],inf);
		}
		else printf("%lld %lld %lld\n",u[i],v[i],w[i]);
	}
}

signed main(){
  scanf("%lld%lld%lld%lld%lld",&n,&m,&l,&s,&t);
  for(int i=1;i<=m;i++){
    scanf("%lld%lld%lld",&u[i],&v[i],&w[i]);
    if(!w[i]){vec.push_back(i);continue;}
    G[u[i]].push_back(make_pair(v[i],w[i]));G[v[i]].push_back(make_pair(u[i],w[i]));
  }
  Dj(s);
//  printf("dis[t]=%d\n",dis[t]);
  if(dis[t]<l) return printf("NO\n"),0;
  if(dis[t]==l){
    printf("YES\n");
    for(int i=1;i<=m;i++){
      printf("%lld %lld %lld\n",u[i],v[i],w[i]==0?inf:w[i]);
    }
    return 0;
  }
  for(int i:vec){
    G[u[i]].push_back(make_pair(v[i],1));
    G[v[i]].push_back(make_pair(u[i],1));
    Dj(s);
		if(dis[t]>l) continue;
		p=i;
		print();
		return 0;
  }
  puts("NO");
  return 0;
}

标签:选写,int,短路,vis,0712,dis,考虑,lld
From: https://www.cnblogs.com/Zimo233/p/17556228.html

相关文章

  • AtCoder Beginner Contest 309 - D(最短路)
    目录D-AddOneEdge法一:dijkstra法二:BFS+队列题目传送门:abc309前面的简单题就不放了D-AddOneEdge题意:给你一个无向图图,分为两个连通块,一个顶点数为n1(1~n1),一个顶点数为n2(n1+1~n1+n2),图中共有m条边。如果现在在两个连通块之间连接一条边,那么顶点1与顶点n1+n2......
  • 2023Tsinghua-HKUSTA G <最短路 Dijkstra>
    题目G.TreasureHuntinMaze代码Code//<堆优化dijkstra>//分别从起点和终点进行dijkstra,得到i,j到起点和终点的最短距离和最短路径数,//则最短路为dis0[x][y]+dis1[x][y],最短路径数为cnt0[x][y]*cnt1[x][y]#include<iostream>#include<algorithm>#incl......
  • SSO2.0 24-20230712
                    ......
  • 230712校内赛
    T1前缀和题目描述给你一个字符串,求所有长度为偶数的前缀在整个字符串中出现的次数和。输入格式共一行,一个字符串S输出格式共一行,输出一个整数,代表长度为偶数的前缀在整个字符串中出现的次数和样例输入数据1abababc输出数据16输入数据2isdashagayisdashagaydas......
  • 20230712练习总结
    AGC009DUninity如果构造一棵点分树,答案是\(\logn\),这是答案上界。将问题转化为每次将若干棵Uninity为\(k\)的树连接到一个点上时将点打上\(k+1\)的\(tag\)。看题面有一个很显然的结论就是两个\(tag=k\)的点间的路径上一定有一个\(tag>k\)。考虑记录\(f_u\)表示......
  • NOIP 2023 模拟赛 20230712 C 论剑
    首先是伟大的题面然后是数据范围先解决1-4号数据点1.枚举每个gcd的值p,统计一次答案,得到最小值(期望得分20)\[ans=\min_{p=2}^{\maxa}\sum^n_{i=1}\min(a_i\bmodp,p-(a_i\bmodp)(a>p))\]2.我们可以发现p仅在为质数时不会重复,也可以将p换为质数(期望得分40)两种的时间复......
  • newcoder61132D <最短路 二分答案>
    题目松鼠回家思路对n个结点的松果个数排序,二分最大松果个数check(x),跑最短路,在不访问比x松果个数多的节点的情况下,从起点到终点消耗的最小体力代码Code#include<iostream>#include<algorithm>#include<vector>#include<cstring>#include<queue>using......
  • HHHOJ #1238. 「NOIP 2023 模拟赛 20230712 D」但战斗还未结束 思考--zhengjun
    赛时想写60pts,结果cxr似乎少算了一点空间,导致我一直没把空间卡过去QWQ。当时不会dfs求拓扑序,这里讲一下。枚举所有非访问过的点依次dfs,每次进行下列操作:找出\(v\)的一个未访问过的入点\(u\),调用dfs(u);找不到\(u\)的时候,把\(v\)加入拓扑序列中。代码#inc......
  • 成语积累 20230712
    惨淡经营:惨淡:苦费心思;经营:筹划。原指煞费苦心地从事绘画或诗文创作,今泛指在困难的境况中艰苦的从事某种事业。作谓语,定语。不吐不茹:不吐刚,不茹柔:不吐坚硬的东西,不吞柔软的东西,即吞坚硬的东西。形容人正直不阿,不欺软怕硬。作谓语,定语。近义:刚正不阿。反义:柔茹刚吐。例句:我们就是......
  • 20230712 讲题
    CF1364DEhab'sLastCorollary简单题。特判掉\(m=n-1\)的情况,此时一定能找到一个大小为\(\left\lceil\frac{k}{2}\right\rceil\)的独立集,二分图染色即可。否则,我们建出dfstree,找到一条连接的两个端点深度之差最小的返祖边,设它为\((u,v)\),且\(dep_u>dep_v\)。......