Week7 作业

A - TT 的魔法猫

众所周知,TT 有一只魔法猫。
这一天,TT 正在专心致志地玩《猫和老鼠》游戏,然而比赛还没开始,聪明的魔法猫便告诉了 TT 比赛的最终结果。TT 非常诧异,不仅诧异于他的小猫咪居然会说话,更诧异于这可爱的小不点为何有如此魔力?
魔法猫告诉 TT,它其实拥有一张游戏胜负表,上面有 N 个人以及 M 个胜负关系,每个胜负关系为 A B,表示 A 能胜过 B,且胜负关系具有传递性。即 A 胜过 B,B 胜过 C,则 A 也能胜过 C。
TT 不相信他的小猫咪什么比赛都能预测,因此他想知道有多少对选手的胜负无法预先得知,你能帮帮他吗?

Input

第一行给出数据组数。
每组数据第一行给出 N 和 M(N , M <= 500)。
接下来 M 行,每行给出 A B,表示 A 可以胜过 B。

Output

对于每一组数据,判断有多少场比赛的胜负不能预先得知。注意 (a, b) 与 (b, a) 等价,即每一个二元组只被计算一次。

Example Input

3
3 3
1 2
1 3
2 3
3 2
1 2
2 3
4 2
1 2
3 4

Example Output

0
0
4

题意:
有一张游戏胜负表,上面若干 个胜负关系,且胜负关系具有传递性,计算出有多少对选手的胜负无法预知。

分析:
本题应该使用Floyd算法,使用一个二维数dis组存储两者间的胜负关系。
从x到y的最短路为min(dis[x][y],dis[x][k]+dis[k][y]),即目前x、y间最短距离 和 x、y通过中间点k连通的距离的较小一方。这里可以进行剪枝,即当dis[x][k]为0时,不论dis[k][y]是否为1,都不能改变dis[x][y]。

代码如下:

#include<iostream>
using namespace std;

int dis[510][510] = { 0 };

int main()
{
	int n, m;
	int num;
	int ans;
	cin >> num;
	while (num--)
	{
		ans = 0;
		cin >> n >> m;
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				dis[i][j] = 0;
			}
		};
		for (int j = 0; j < m; j++)
		{
			int a, b;
			cin >> a >> b;
			dis[a - 1][b - 1] = 1;
		}
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				if (dis[j][i] == 1)
				{
					for (int k = 0; k < n; k++)
						dis[j][k] = dis[j][k] | (dis[j][i] & dis[i][k]);
				}
			}
		}
		for (int i = 0; i < n; i++)
		{
			for (int j = i + 1; j < n; j++)
			{
				if (dis[i][j] == 0 && dis[j][i] == 0)
					ans++;
			}
		}
		cout << ans << endl;
	}
	return 0;
}

B - TT 的旅行日记

众所周知,TT 有一只魔法猫。
今天他在 B 站上开启了一次旅行直播,记录他与魔法猫在喵星旅游时的奇遇。 TT 从家里出发,准备乘坐猫猫快线前往喵星机场。猫猫快线分为经济线和商业线两种,它们的速度与价钱都不同。当然啦,商业线要比经济线贵,TT 平常只能坐经济线,但是今天 TT 的魔法猫变出了一张商业线车票,可以坐一站商业线。假设 TT 换乘的时间忽略不计,请你帮 TT 找到一条去喵星机场最快的线路,不然就要误机了!

Input

输入包含多组数据。每组数据第一行为 3 个整数 N, S 和 E (2 ≤ N ≤ 500, 1 ≤ S, E ≤ 100),即猫猫快线中的车站总数,起点和终点(即喵星机场所在站)编号。
下一行包含一个整数 M (1 ≤ M ≤ 1000),即经济线的路段条数。
接下来有 M 行,每行 3 个整数 X, Y, Z (1 ≤ X, Y ≤ N, 1 ≤ Z ≤ 100),表示 TT 可以乘坐经济线在车站 X 和车站 Y 之间往返,其中单程需要 Z 分钟。
下一行为商业线的路段条数 K (1 ≤ K ≤ 1000)。
接下来 K 行是商业线路段的描述,格式同经济线。
所有路段都是双向的,但有可能必须使用商业车票才能到达机场。保证最优解唯一。

Output

对于每组数据,输出3行。第一行按访问顺序给出 TT 经过的各个车站(包括起点和终点),第二行是 TT 换乘商业线的车站编号(如果没有使用商业线车票,输出"Ticket Not Used",不含引号),第三行是 TT 前往喵星机场花费的总时间。
本题不忽略多余的空格和制表符,且每一组答案间要输出一个换行

Example Input

4 1 4
4
1 2 2
1 3 3
2 4 4
3 4 5
1
2 4 3

Example Output

1 2 4
2
5

题意:
在图中找到一条花费时间最短的路线并输出。

分析:
本题类似于求单源最短路径,但要对商业线进行特殊处理并输出经过的点以及中转的点。
算法思想为从起点和终点分别进行两次dijkstra,分别记录单源最短路,然后对商业线进行枚举并记下使用商业线的最小值,与不使用商业线的最小值进行比较,最后输出最小值。

代码如下:

#include <iostream>
#include <stdio.h>
#include <vector>
#include <queue>
#include <cmath>
#include <string.h>
using namespace std;

const int inf = 100000000;

struct zhan
{
    int xx, tp;
};

struct edge
{
    int a;
    int to, w;
    bool operator<(const edge& ee)const
    {
        return w > ee.w;
    }
};

int n, S, E;
int m, k, cnt = 0, off = -1;
int dis[510][2];
int road[510];
zhan pre[510][2];
vector<edge> e[510];

void find(int end, int p)
{
    if (end == S) 
    {
        road[cnt] = S;
        cnt++;
        return;
    }
    zhan before = pre[end][p];
    if (before.tp == 1)
    {
        off = before.xx;
        p = 0;
    }
    find(before.xx, p);
    road[cnt] = end;
    cnt++;
    return;
}

int main()
{
    int kk = 0;
    while (scanf("%d", &n) != EOF)
    {
        scanf("%d %d", &S, &E);
        scanf("%d", &m);
        for (int i = 0; i < m; i++)
        {
            int f, t, ww;
            scanf("%d %d %d", &f, &t, &ww);
            e[f].push_back({ 0, t, ww });
            e[t].push_back({ 0, f, ww });
        }
        scanf("%d", &k);
        for (int i = 0; i < k; i++)
        {
            int f, t, ww;
            scanf("%d %d %d", &f, &t, &ww);
            e[f].push_back({ 1, t, ww });
            e[t].push_back({ 1, f, ww });
        }
        priority_queue<edge> q;
        memset(pre, 0, sizeof(pre));
        for (int i = 0; i < 510; i++)
        {
            dis[i][0] = inf;
            dis[i][1] = inf;
        }
        dis[S][0] = 0;
        dis[S][1] = 0;
        q.push({ 0, S, 0 });
        while (!q.empty())
        {
            int x = q.top().to;
            q.pop();
            for (int i = 0; i < e[x].size(); i++)
            {
                int y = e[x][i].to, ww = e[x][i].w, t = e[x][i].a;
                if (!t)
                {
                    if (dis[y][0] > dis[x][0] + ww)
                    {
                        zhan pp;
                        pp.xx = x;
                        pp.tp = t;
                        pre[y][0] = pp;
                        dis[y][0] = dis[x][0] + ww;
                        q.push({ 0, y, dis[y][0] });
                    }
                    if (dis[y][1] > dis[x][1] + ww)
                    {
                        zhan pp;
                        pp.xx = x;
                        pp.tp = t;
                        pre[y][1] = pp;
                        dis[y][1] = dis[x][1] + ww;
                        q.push({ 1, y, dis[y][1] });
                    }
                }
                else
                {
                    if (dis[y][1] > dis[x][0] + ww)
                    {
                        zhan pp;
                        pp.xx = x;
                        pp.tp = t;
                        pre[y][1] = pp;
                        dis[y][1] = dis[x][0] + ww;
                        q.push({ 1, y, dis[y][1] });
                    }
                }
            }
        }
        cnt = 0;    
        off = -1;
        int ans;
        memset(road, 0, sizeof(road));
        if (dis[E][0] < dis[E][1])
        {
            ans = dis[E][0];
            find(E, 0);
        }
        else
        {
            ans = dis[E][1];
            find(E, 1);
        }
        if (!kk)		
            kk = 1;
        else	
            printf("\n");
        for (int i = 0; i < cnt; i++)
        {
            if (i != cnt - 1)  
                printf("%d ", road[i]);
            if (i == cnt - 1)  
                printf("%d\n", road[i]);
        }
        if (off == -1)   
            printf("Ticket Not Used\n");
        else    
            printf("%d\n", off);
        printf("%d\n", ans);
        for (int i = 0; i < 510; i++)      
            e[i].clear();
    }
    return 0;
}

C - TT 的美梦

这一晚,TT 做了个美梦!
在梦中,TT 的愿望成真了,他成为了喵星的统领!喵星上有 N 个商业城市,编号 1 ~ N,其中 1 号城市是 TT 所在的城市,即首都。
喵星上共有 M 条有向道路供商业城市相互往来。但是随着喵星商业的日渐繁荣,有些道路变得非常拥挤。正在 TT 为之苦恼之时,他的魔法小猫咪提出了一个解决方案!TT 欣然接受并针对该方案颁布了一项新的政策。
具体政策如下:对每一个商业城市标记一个正整数,表示其繁荣程度,当每一只喵沿道路从一个商业城市走到另一个商业城市时,TT 都会收取它们(目的地繁荣程度 - 出发地繁荣程度)^ 3 的税。
TT 打算测试一下这项政策是否合理,因此他想知道从首都出发,走到其他城市至少要交多少的税,如果总金额小于 3 或者无法到达请悄咪咪地打出 ‘?’。

Input

第一行输入 T,表明共有 T 组数据。(1 <= T <= 50)
对于每一组数据,第一行输入 N,表示点的个数。(1 <= N <= 200)
第二行输入 N 个整数,表示 1 ~ N 点的权值 a[i]。(0 <= a[i] <= 20)
第三行输入 M,表示有向道路的条数。(0 <= M <= 100000)
接下来 M 行,每行有两个整数 A B,表示存在一条 A 到 B 的有向道路。
接下来给出一个整数 Q,表示询问个数。(0 <= Q <= 100000)
每一次询问给出一个 P,表示求 1 号点到 P 号点的最少税费。

Output

每个询问输出一行,如果不可达或税费小于 3 则输出 ‘?’。

Example Input

2
5
6 7 8 9 10
6
1 2
2 3
3 4
1 5
5 4
4 5
2
4
5
10
1 2 4 4 5 6 7 8 9 10
10
1 2
2 3
3 1
1 4
4 5
5 6
6 7
7 8
8 9
9 10
2
3 10

Example Output

Case 1:
3
4
Case 2:
?
?

题意:
在图中找出某个节点到剩余每个节点的最小消耗路线。

分析:
该题要求单源最短路径,并且存在负边的情况,只能用SPFA算法。
先将起点到所有点的距离初始化为inf并将起点入队,当队列不为空时,每次取队首元素,将其出队并将label值修改为0。当点出现在队列中的次数大于等于图中的点数时,存在负环,输出“?”,当要缴纳的税小于3时也输出“?”。

代码如下:

#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;

const int inf = 1000000000;

struct city 
{
	int e;
	int mo;
};

int T, N, M, Q, P;
int a[210], dis[210], in[210], cnt[210], fu[210], label[210];

void init()
{
	for (int i = 0; i < 210; i++)
	{
		dis[i] = inf;
		in[i] = cnt[i] = fu[i] = label[i] = 0;
	}
}

void SPFA(vector<city> ro[210])
{
	queue<int> q;
	dis[1] = 0;
	in[1] = 1;
	q.push(1);
	while (!q.empty())
	{
		int num = q.front();
		q.pop();
		in[num] = 0;
		for (int i = 0; i < ro[num].size(); i++)
		{
			int end = ro[num][i].e;
			int m = ro[num][i].mo;
			if (dis[end] > (dis[num] + m))
			{
				dis[end] = dis[num] + m;
				cnt[end] = cnt[num] + 1;
				if (cnt[end] >= N)
				{
					fu[end] = 1;
					queue<int> p;
					p.push(end);
					label[end] = 1;
					while (!p.empty())
					{
						int ff = p.front();
						p.pop();
						for (int k = 0; k < ro[ff].size(); k++)
						{
							int temp = ro[ff][k].e;
							fu[temp] = 1;
							if (label[temp] == 0)
							{
								label[temp] = 1;
								p.push(temp);
							}
						}
					}
				}
				if ((in[end] != 1) && fu[end] == 0)
				{
					q.push(end);
					in[end] = 1;
				}
			}
		}
	}
}

int main()
{
	cin >> T;
	int t = T;
	while (T--)
	{
		vector<city> road[210];
		cin >> N;
		for (int i = 1; i <= N; i++)
			cin >> a[i];
		cin >> M;
		for (int i = 0; i < M; i++)
		{
			int A, B;
			cin >> A >> B;
			city c;
			c.e = B;
			c.mo = pow((a[B] - a[A]), 3);
			road[A].push_back(c);
		}
		init();
		SPFA(road);
		cin >> Q;
		cout << "Case " << t - T << ":" << endl;
		for (int i = 0; i < Q; i++)
		{
			cin >> P;
			if (dis[P] == inf || fu[P] == 1 || dis[P] < 3)
				cout << "?" << endl;
			else
				cout << dis[P] << endl;
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值