【2018/08/18测试T3】【SOJ 964】Travel

【题目】

题目描述:

小 A 要进行一次旅行。这回他要在序号为 1 到 n 的 n 个城市之间旅行。这 n 个城市之间共有 m 条连接两个城市的单行公路,对于第 i 条公路的风景有一个评分 ai。小 A 有一个要求:挑选旅行路线时经过某条路时看到的风景比上一条经过的公路的风景评分更高。小 A 想看到尽可能多的风景,请你告诉他他能找到的最长的满足他要求旅行路线有多长。(每条公路长度视为1,可以重复经过一个城市)

输入格式:

第一行为两个整数数 n,m。
接下来 m 行,每行三个整数 xi,yi,ai 分别代表每条公路的起点序号、终点序号、风景分数。

输出格式:

输出一个整数,为满足要求的最长路线的长度。

样例数据:

输入

3 3
1 2 1
2 3 2
3 1 3

输出

3

备注:

【样例说明】
最长路径为:(1->2->3->1)

【数据范围】
对 30% 的输入数据,n ≤ 10;m ≤ 50;ai ≤ 100
对 60% 的输入数据,n ≤ 1000;m ≤ 5000;ai ≤ 1000
对 100% 的输入数据,n,m ≤ 300000;1 ≤ ai ≤ 100000

 

【分析】

emmm,一道非常巧妙的题

用 f [ i ] 表示到达 i 时,最长路线的长度

我们将边从小到大排序,依次加边,这样做的好处是每次加边时就可以直接 f [ v ] = max ( f [ v ] , f [ u ] + 1 ),就不用判断边的大小关系了,因为后加进来的边肯定比之前加进来的边大

还有一个小细节是如果有权值相等的边的话,这样可能会出错,具体可以用这组数据感受一下“4 3;1 2 1;2 3 2;3 4 2”(分号代表换行)这个时候我们就用一个临时数组 g 来记录还没加这些边时的 f,方程改成 f [ v ] = max ( f [ v ] , g[ u ] + 1 )

 

【代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 300005
using namespace std;
int g[N],f[N];
int t,first[N],u[N],v[N],next[N];
void add(int z)
{
	t++;
	next[t]=first[z];
	first[z]=t;
}
int main()
{
//	freopen("travel.in","r",stdin);
//	freopen("travel.out","w",stdout);
	int n,m,i,j,w,ans=0;
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;++i)
	{
		scanf("%d%d%d",&u[i],&v[i],&w);
		add(w);   //按照边权建链表,这样之后从前往后枚举就达到了排序的目的
	}
	for(i=1;i<=100000;++i)
	{
		for(j=first[i];j;j=next[j])
		  g[u[j]]=f[u[j]];   //建立临时数组
		for(j=first[i];j;j=next[j])
		  f[v[j]]=max(f[v[j]],g[u[j]]+1);   //转移
	}
	for(i=1;i<=n;++i)
	  ans=max(ans,f[i]);
	printf("%d",ans);
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
详细设计: 1. 框图 ``` +----------------+ +------------------------+ | | | | | 用户操作界面 |<--------->| 服务器处理 | | | | | +----------------+ +------------------------+ ``` 2. 程序实现 (1)添加学生信息 ``` void add_student_info(char* file_name, char* student_id, char* student_name, float student_score) { FILE* fp = fopen(file_name, "a"); fprintf(fp, "%s\t%s\t%.2f\n", student_id, student_name, student_score); fclose(fp); } ``` (2)修改学生信息 ``` void modify_student_info(char* file_name, char* student_id, char* student_name, float student_score) { FILE* fp = fopen(file_name, "r"); FILE* tmp_fp = fopen("tmp.txt", "w"); char buf[1024]; int found = 0; while (fgets(buf, sizeof(buf), fp) != NULL) { char id[10], name[20]; float score; sscanf(buf, "%s\t%s\t%f", id, name, &score); if (strcmp(id, student_id) == 0) { fprintf(tmp_fp, "%s\t%s\t%.2f\n", student_id, student_name, student_score); found = 1; } else { fprintf(tmp_fp, "%s", buf); } } fclose(fp); fclose(tmp_fp); if (found) { remove(file_name); rename("tmp.txt", file_name); } else { remove("tmp.txt"); } } ``` (3)删除学生信息 ``` void delete_student_info(char* file_name, char* student_id) { FILE* fp = fopen(file_name, "r"); FILE* tmp_fp = fopen("tmp.txt", "w"); char buf[1024]; int found = 0; while (fgets(buf, sizeof(buf), fp) != NULL) { char id[10]; sscanf(buf, "%s", id); if (strcmp(id, student_id) == 0) { found = 1; } else { fprintf(tmp_fp, "%s", buf); } } fclose(fp); fclose(tmp_fp); if (found) { remove(file_name); rename("tmp.txt", file_name); } else { remove("tmp.txt"); } } ``` (4)查询学生信息 ``` void query_student_info(char* file_name, char* student_id) { FILE* fp = fopen(file_name, "r"); char buf[1024]; int found = 0; while (fgets(buf, sizeof(buf), fp) != NULL) { char id[10], name[20]; float score; sscanf(buf, "%s\t%s\t%f", id, name, &score); if (strcmp(id, student_id) == 0) { printf("%s\t%s\t%.2f\n", id, name, score); found = 1; break; } } fclose(fp); if (!found) { printf("Student info not found!\n"); } } ``` (5)显示所有学生信息 ``` void display_all_student_info(char* file_name) { FILE* fp = fopen(file_name, "r"); char buf[1024]; while (fgets(buf, sizeof(buf), fp) != NULL) { char id[10], name[20]; float score; sscanf(buf, "%s\t%s\t%f", id, name, &score); printf("%s\t%s\t%.2f\n", id, name, score); } fclose(fp); } ``` 3. 核心步骤图 (1)添加学生信息 ![add_student_info](https://i.imgur.com/0xZ8JYf.png) (2)修改学生信息 ![modify_student_info](https://i.imgur.com/8fO8mY0.png) (3)删除学生信息 ![delete_student_info](https://i.imgur.com/FXiw3xq.png) (4)查询学生信息 ![query_student_info](https://i.imgur.com/1RUK2gX.png) (5)显示所有学生信息 ![display_all_student_info](https://i.imgur.com/SOJ8LhL.png)

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值