Educational Codeforces Round 54 (Rated for Div. 2) D. Edge Deletion(Dijkstra理解题)

探讨了一道基于最短路径算法的变种题目,通过模拟Dijkstra算法的入堆过程,实现选择k条边以最大化子图上的最短路径点数量。详细介绍了题目的背景、解决思路及代码实现。

思路来源

马石页老师&&张舟亢学长

题意

给你一个n点m边的原图,要求只保留这个图的k条边,

使子图上的最短路点尽可能多。

最短路点是指到1号节点的最短距离,在原图和子图的值相同。

要求输出子图边的编号,按加入的顺序对边进行编号1-m。

题解

模拟dijkstra的入堆过程,

由于dijkstra的贪心选点思想,每次一定选的是到顶点最近的点。

因此,必有一次松弛操作,使得一条边贡献出一个最短路点。

因此,开一个存结构体的优先队列,

我们只要一松弛,就把贡献松弛的边的id塞进优先队列里,

取出优先队列顶的点的时候(已按距离从小到大排序)

查一下是从哪个id的边使这个点成为到顶点的最短距离点(即当前被贪心选中的点),

然后把这个id加到ans里,满足k条return即可。

心得

最短路题变种好多啊QAQ

稍微考点概念就不会了GG

这题没开ll会被hack掉,

CF榜上hack率惊人QAQ

代码

#include <iostream>
#include <algorithm> 
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <functional>
const int INF=0x3f3f3f3f;
const int maxn=3e5+10; 
const int mod=1e9+7;
const int MOD=998244353;
const double eps=1e-7;
typedef long long ll;
#define vi vector<int> 
#define si set<int>
#define pli pair<ll,int> 
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a)) 
using namespace std;
int head[maxn],cnt,n,m,k;
bool vis[maxn];
ll dis[maxn]; 
struct edge{int to,nex,id;ll w;}e[maxn<<1];
struct node
{
  ll w;
  int id,v;
  node(ll a,int b,int c):w(a),id(b),v(c){
  } 
};
bool operator>(node a,node b)
{
	return a.w>b.w;
}
priority_queue<node,vector<node>,greater<node> >q;
vector<int>ans;
void init()
{
	rep(i,0,n-1)dis[i]=1e18;
	cnt=0;
	mem(head,-1);
}
void add(int u,int v,ll w)
{
	e[cnt].to=v;
	e[cnt].w=w;
	e[cnt].id=cnt/2;
	e[cnt].nex=head[u];
	head[u]=cnt++;
}
void dijkstra(int s)
{
	q.push(node(0,-1,s));//说明从哪条边转移到这点的 
	dis[s]=0;
	while(!q.empty())
	{
		node tmp=q.top();
		q.pop();
		ll w=tmp.w;
		int id=tmp.id,v=tmp.v;
		if(vis[v]||w>dis[v])continue;
		vis[v]=1;
		if(id!=-1)ans.push_back(id);
		if(ans.size()==k)return;
		for(int i=head[v];~i;i=e[i].nex)
		{
			int to=e[i].to,id=e[i].id;
			ll w=e[i].w;
			if(dis[to]>dis[v]+w)
			{
				dis[to]=dis[v]+w;
				q.push(node(dis[to],id,to));
			}
		}
	}
} 
int main()
{ 
    sci(n),sci(m),sci(k);
    init();
    rep(i,0,m-1)
    {
    	int u,v;
    	ll w;
    	sci(u),sci(v),scll(w);
    	u--,v--;
    	add(u,v,w);
    	add(v,u,w);
    }
    dijkstra(0);
    int len=ans.size();
    printf("%d\n",len);
    if(len)
    {
    	printf("%d",1+ans[0]);
    	rep(i,1,len-1)
    	printf(" %d",1+ans[i]);
    	puts("");
    }
	return 0;
}

 

### 关于Codeforces Educational Round 172 Problem D 的解决方案 对于Codeforces Educational Round 172中的D,虽然未直接提供该目具体描述以及官方解答[^2],可以基于过往相似难度和类型的目给出一般性的解决思路。 #### 目分析 通常情况下,D级别的目会涉及到较为复杂的算法设计或是数据结构的应用。这类问往往需要参赛者具备良好的编程基础、逻辑思维能力以及对特定算法的理解掌握程度。针对不同性质的问(如图论、动态规划、字符串处理等),采取相应的策略来构建模型并求解是常见的方法之一。 #### 解决方案框架 假设此属于某种典型问类别,则可以根据其特点制定如下通用框架: - **输入解析**:仔细阅读目说明,明确给定条件与目标函数之间的关系。 - **核心概念理解**:深入剖析目背后所隐藏的关键知识点或技巧点,这可能涉及但不限于贪心算法、二分查找、树形DP等方面的知识。 - **边界情况考虑**:考虑到极端测试用例的存在,在编写程序时要特别注意各种特殊情况下的行为表现,确保代码鲁棒性强。 - **优化空间复杂度/时间效率**:当面对大数据集时,应尽可能寻找更高效的实现方式减少不必要的计算开销;比如利用哈希表加速查询速度,通过位运算代替常规算术操作提高性能等等。 ```cpp // 假设这是一个简化版的伪代码示例 #include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; // 输入参数 vector<int> data(n); for(auto& d : data){ cin>>d; } // 主体逻辑部分省略... cout << "Result"; return 0; } ``` 由于缺乏具体的目细节,上述内容仅作为参考模板展示如何着手准备类似的竞赛挑战。为了获得更加精准的帮助建议查阅官方解文档或者参与社区论坛交流获取更多信息资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小衣同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值