acwing 第二场周赛

acwing 3626.三元一次方程

链接:https://www.acwing.com/problem/content/3629/

题目描述

2

解题思路

方程前面系数不变,那么直接进行一个环的循,枚举x和y的值就行,因为z=(n-3x-5y)/7

再看一下数据,n才1000,x最大为333,y最大为200,1000个数据复杂度就是O(333*200 *1000)

也就是O(6e7),时间绝对够

结束,没难点不用上代码

acwing 3627.最大差值

链接:https://www.acwing.com/problem/content/description/3630/

题目描述

1

解题思路

因为最小值最小只能为0,所以直接找到k项最大的数加到最大值上就行了

实际就是,给定一个长度为n的非负整数序列,让你求出前k+1项最大值的和

所以sort一遍再for循环1~k+1加起来就行了

结束,没难点不用上代码

acwing 3268.边的删减

链接:https://www.acwing.com/problem/content/description/3631/

题目描述

3

解题思路

最短路树

4

最短路树是由每个点到起点的最短路径组成的,存储着每个点的最短路径

如果一个点有多条最短路,那么只用随便保留一个就行了

一个无向图中,只要最短路树上的边没被删除,那么这个点离起点的最短距离也不变

也就是说,除了最短路树上的边,其他边都是无用的,可以随便删

如果能保留的边不够组成一个最短路树,那么“优秀点”的数量就是能保留的边数k,因为最短路树少一条边就少一个叶子结点

那么我们只用求出最短路树,然后从根节点开始从前往后尽可能多的保留最短路树上的边就行了

结束,上代码

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef pair<LL,int> PII;
const int N=1e5+10,M=2e5+10;
int n,m,k;
int head[N],e[M],ne[M],w[M],idx;
int id[M];
LL dis[N];//边是1e9,所以最短距离有可能爆int 
bool vis[N];
vector<int> ans;
void add(int a,int b,int c,int d)  // 添加一条边a->b,边权为c
{
    e[idx]=b;
	w[idx]=c;
	id[idx]=d;
	ne[idx]=head[a];
	head[a]=idx++;
}
void dijkstra()  // 求1号点到n号点的最短路距离
{
    memset(dis,0x3f,sizeof(dis));
    dis[1] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push(make_pair(0, 1));
    while(heap.size())
    {
        PII t=heap.top();
        heap.pop();
        int x=t.second;
        if(vis[x]) continue;
        vis[x]=true;
        for (int i=head[x];i!=-1;i=ne[i])
        {
            int j=e[i];
            //cout<<i<<" "<<x<<" "<<j<<endl;
            if (dis[j]>dis[x]+w[i])
            {
                dis[j]=dis[x]+w[i];
                heap.push(make_pair(dis[j],j));
            }
        }
    }
}
void dfs(int x){
	vis[x]=true;
	for(int i=head[x];i!=-1;i=ne[i]){
		int j=e[i];
		//cout<<w[i]<<" "<<dis[i]<<" "<<dis[j]<<endl;
		if(!vis[j]&&dis[j]==dis[x]+w[i]){
			if(ans.size()<k) ans.push_back(id[i]);
			dfs(j);
		}
	}
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c,i);
        add(b,a,c,i);
    }
    dijkstra();
    memset(vis,0,sizeof(vis));
    dfs(1);
    //for(int i=1;i<=n;i++) cout<<dis[i]<<endl;
    printf("%d\n",ans.size());
    for(int i=0;i<ans.size();i++) printf("%d ",ans[i]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值