Noip模拟题解题报告

Pro

题目链接

Sol

公交车

这道题,要么点多要么边多。

正解是点多,因为我们要在公交线路上的任意两点间连一条边,这样就会产生很多的边,但是我们可以加一个虚点,向虚点连边就少很多,因为上了公交车就付一次费,所以只需要一条边有权值就好。

然后就是水的dij优化最短路。

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#define INF 1e18
using namespace std;

struct Node {
	long long to , next , len;
};
Node e[1000005];
struct Que {
	long long num , len;
	Que(long long nn , long long dd) {
		num = nn , len = dd;
	}
	bool operator < (const Que &a) const {
		return len > a.len;
	}
};
long long n , m , k , s , tot , head[200005] , dis[200005] , z[200005];

void add(long long x , long long y , long long z) {
	tot++;
	e[tot].next = head[x];
	e[tot].to = y;
	e[tot].len = z;
	head[x] = tot;
}

void dij(long long x) {
	priority_queue<Que>q;
	for(long long i=1; i<=n; i++)
		dis[i] = INF;
	dis[x] = 0;
	q.push(Que(x,dis[x]));
	while(!q.empty()) {
		Que u = q.top();
		q.pop();
		if(u.len != dis[u.num])
			continue;
		for(long long i=head[u.num]; i; i=e[i].next)
			if(dis[e[i].to] > u.len + e[i].len) {
				dis[e[i].to] = u.len + e[i].len;
				q.push(Que(e[i].to , dis[e[i].to]));
			}
	}
}

int main() {
	freopen("transprt.in","r",stdin);
	freopen("transprt.out","w",stdout);
	scanf("%lld%lld%lld%lld",&n,&m,&k,&s);
	for(long long i=1; i<=m; i++) {
		long long x , y , z;
		scanf("%lld%lld%lld",&x,&y,&z);
		add(x , y , z);
		add(y , x , z);
	}
	for(long long i=1; i<=k; i++) {
		long long x , y , z;
		scanf("%lld%lld",&x,&y);
		for(long long j=1; j<=y; j++) {
			scanf("%lld",&z);
			add(z , n+i , x);
			add(n+i , z , 0);
		}
	}
	n += k;
	dij(s);
	for(long long i=1; i<=n-k; i++)
		printf("%lld ",dis[i]);
	return 0;
}

灌溉

话说出题人真是的……两道题用到的思想差不多。

建一个虚点,虚点到各个点的距离为建水库的代价,问题就转化为:求最便宜的引水花费……

裸的MST,直接克鲁斯卡尔……

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define INF 2147483647
using namespace std;

struct Road {
	int d1 , d2 , len;
	bool operator < (const Road &a) const {
		return len < a.len;
	}
};
Road v[500005];
int n , top , val[305] , P[305][305] , fa[305] , ans;
inline int mymin(int a , int b) { return a<b?a:b; }

int find(int x) {
	if(fa[x]!=x)
		return find(fa[x]);
	return fa[x];
} 

void klus() {
	int cnt = 0;
	for(int i=1; i<=top; i++) {
		int fx = find(v[i].d1) , fy = find(v[i].d2);
		if(fx != fy) {
			cnt++;
			fa[fy] = fx;
			ans += v[i].len;
			if(cnt == n)
				return ;
		}
	}
}

void init() {
	for(int i=1; i<=n; i++)
		for(int j=i+1; j<=n; j++) {
			top++;
			v[top].d1 = i;
			v[top].d2 = j;
			v[top].len = P[i][j];		
		} 
	for(int i=1; i<=n; i++)
		fa[i] = i;
	sort(v+1 , v+top+1);
}

int main() {
	freopen("irrigate.in","r",stdin);
	freopen("irrigate.out","w",stdout);
	scanf("%d",&n);
	for(int i=1; i<=n; i++) {
		int x;
		scanf("%d",&x);
		top++;
		v[top].d1 = i;
		v[top].d2 = n+1;
		v[top].len = x;
	}
	for(int i=1; i<=n; i++)
		for(int j=1; j<=n; j++)
			scanf("%d",&P[i][j]);
	init();
	klus();
	printf("%d",ans);
	return 0;
}

对决

emmm,最简单的dfs……

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

struct Node {
	int to , next;
};
Node e[200005];
int n , m , head[100005] , tot , cdu[100005] , flag[100005][3] , opt[100005] , cnt , num[100005];

void add(int x , int y) {
	tot++;
	e[tot].next = head[x];
	e[tot].to = y;
	head[x] = tot;
}

void dfs(int u , int f) {
	if(opt[u]) {
		flag[f][opt[u]]++;
		return ;
	}
	for(int i=head[u]; i; i=e[i].next)
		dfs(e[i].to , u);
	if(flag[u][1])
		opt[u] = 2;
	else
		opt[u] = 1;
	flag[f][opt[u]]++;
}

int main() {
	freopen("duel.in","r",stdin);
	freopen("duel.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1; i<=m; i++) {
		int x , y;
		scanf("%d%d",&x,&y);
		add(x , y);
		cdu[x]++;
	}
	for(int i=1; i<=n; i++)
		if(!cdu[i])
			num[++cnt] = i;
	sort(num+1 , num+cnt+1);
	for(int i=1; i<=cnt; i++) {
		int x;
		scanf("%d",&x);
		opt[num[i]] = x + 1;
	}
	for(int i=1; i<=n; i++)
		if(!opt[i])
			dfs(i,0);
	for(int i=1; i<=n; i++) {
		if(opt[i]==1)
			printf("Last\n");
		else
			printf("First\n");
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NOIP(全国青少年信息学奥林匹克竞赛)是中国国内最高水平的信息学竞赛之一,是计算机领域的重要赛事。针对NOIP模拟题,通常是为了帮助参赛者熟悉比赛形式和题型,提供足够的训练机会。 数据下载是NOIP比赛中的一个重要环节,因为参赛者需要根据提供的数据集进行程序开发和测试。数据下载一般通过网络进行,参赛者需要在指定的时间段内下载数据集到自己的计算机上。 在进行NOIP模拟题数据下载时,我们可以按照以下步骤进行操作: 1. 确认下载链接:NOIP官方会提供下载数据集的链接或者FTP地址,参赛者需要确认链接是否可用和正确。 2. 选择下载工具:根据自己的需求,参赛者可以选择合适的下载工具进行操作。常见的下载工具有浏览器内置下载工具、迅雷、IDM等,可以根据个人的习惯和需求选择合适的下载工具。 3. 打开下载工具:根据所选择的下载工具类型,打开对应的软件,进入下载界面。 4. 输入下载链接:将NOIP提供的数据集下载链接复制粘贴到下载工具的链接输入框中,点击确定或开始进行下载。 5. 等待下载完成:根据数据集的大小和网络速度不同,下载时间会有所变化。参赛者需要耐心等待下载完成,确保数据集完整地保存到自己的计算机上。 6. 验证数据完整性:下载完成后,参赛者需要验证数据集的完整性,确保所有文件都成功地保存到指定位置。可以进行文件大小的比对或者逐个文件的校验来检查数据完整性。 通过以上步骤,参赛者可以成功地进行NOIP模拟题数据的下载。在实际比赛中,一个高效的数据下载过程可以提高参赛者的准备时间和竞争力,确保能够充分利用所提供的数据集进行开发和测试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值