图论入门---拓扑排序的应用
admin
2024-05-04 01:40:57
0

    最近研究了几道图论的题目,都是图论入门的算法,用的比较多的就是拓扑排序,多用于有着先后顺序的题目,也可以用来判断环,做个小总结。

杂物

题目链接:杂务 - 洛谷 

    这一题需要计算最短的时间,利用了记忆化搜索的方式。将每一项工作抽象为图中的节点,所有前面需要完成的也就是节点的前驱,因为每一项工作完成所需要的最短总时长其实就是完成前面需要的工作的最早时长再加上这个工作的时长,因为所有工作的最早完成时间在一开始是未知的,所以需要先把所有前驱给计算出来, 所以搜索是需要先更新前驱结点,如果计算过了就直接返回结果,本质上也是拓扑排序,利用转移方程finalT[i]=min(finalT[...])+t[i],也就是当前工作的时长加上最早前驱计算每个节点,确定最终答案。

#include
#include
#include
#define Max 100100
using namespace std;
vectorv1[Max];
int t[Max];//每个点的时间
int flag[Max];//标记每个点的访问情况
int finalT[Max];//标记最终的答案
int n;int dfs(int x)
{if (flag[x])return finalT[x];for (int i = 0; i < v1[x].size(); i++)finalT[x] = max(finalT[x], finalT[v1[x][i]] + t[x]);flag[x] = 1;return finalT[x];
}int main()
{scanf("%d", &n);int x, y;for (int i = 1; i <= n; i++){scanf("%d%d", &x, t + i);while ( scanf("%d",&y) && y)//这样写更简洁{v1[x].push_back(y);//这个方笛一定要注意,给的形式是前驱}}int ans = 0;for (int i = 1; i <= n; i++)finalT[i] = t[i];for (int i = 1; i <= n; i++)ans = max(ans, dfs(i));printf("%d\n", ans);return 0;
}

 最大食物链计数

题目链接:最大食物链计数 - 洛谷 

    这一题需要计算食物链的总数,将每个生物抽象为图中节点,一个生物吃另一个生物就是作为前驱。那么只有一个节点只有入度而没有出度才可以算作一条完整的食物链,对于每个节点,到达这个节点所有的食物链总数其实就是所有指向这个节点的食物链总和,也就是num[i]=∑num[j],j是i的前驱, 初始状态是将每个只有出度的点作为1,最后求和是对所有没有出度的求和。

#include
#include
#include
using namespace std;
#define ll long long
#define mod 80112002
vectorv[10000];
int n,m;
int flag[10000];
int vis[10000];//标记这个点有没有出度int cal(int x)
{if (flag[x])return flag[x];if (v[x].size() == 0)return flag[x] = 1;//没有前驱就是1for (int i = 0; i < v[x].size(); i++){flag[x] = (flag[x] + cal(v[x][i])) % mod;}return flag[x];
}int main()
{scanf("%d%d", &n, &m);int x, y;for (int i = 1; i <= m; i++){scanf("%d%d", &x, &y);vis[x] = 1;v[y].push_back(x);}int ans = 0;for (int i = 1; i <= n; i++){if(!vis[i])ans = (ans + cal(i)) % mod;//cal计算所有前驱的和}printf("%d\n", ans);return 0;
}

排序

题目链接:排序 - 洛谷

    这道题因为有三种情况,也就是矛盾---出现环,无法排序---没有唯一拓扑序列,排序完成--有唯一的拓扑序列,恰好考察了拓扑排序的应用。这一题读入点要标记出现的点,在排序时候只要出现的点都有了那么排序就完成了,但是在排序中会出现几种情况:第一种是找了一轮都找不到度为0的点,那么这时候是出现矛盾了;第二种要是找了一轮找到了好几个度为0的那么就无法确定,一开始我是吃了这里的亏,也就是在函数中出现无法确定直接返回,但是由于无法确定还可能最终是矛盾的,所以不可以直接返回,最终返回是矛盾优先,因为直接就不用后面的判断了;第三种就是排序完成了,出现的字母个数也是等于总个数,那么就可以退出了。

#include
#include
#include
#include
using namespace std;
vectorv[200];
int du[200],du2[200];
char res[30];
bool exist[200];
bool flag[200];
queueq;
int n, m;int topo_sort(int cag)
{int cnt = 0;int not_sure = 0;for (int i = 'A'; i <= 'Z'; i++){int first = 0;//标记是不是只有一个入队if (exist[i] && du2[i] == 0){if (!first)first = 1;else not_sure = 1;q.push(i);res[++cnt] = i;}}if (q.empty())return -1;//矛盾while (!q.empty()){int x = q.front();q.pop();int first = 0;for (int i = 0; i < v[x].size(); i++){du2[v[x][i]]--;if (!du2[v[x][i]]){if (!first)first = 1;else not_sure = 1;q.push(v[x][i]);res[++cnt] = v[x][i];}}}//printf("cnt=%d,cag=%d\n", cnt,cag);if (cnt != cag)return -1;//如果没排序完,那么就是有环,也就是矛盾if (not_sure)return 0;//不确定return 1;//排序完毕
}int main()
{scanf("%d%d", &n, &m);char x, y;int cag = 0;//当前有的种类for (int i = 1; i <= m; i++){scanf(" %c<%c", &x, &y);cag += (1-exist[x] + 1-exist[y]);exist[x] = 1;exist[y] = 1;//printf("%c:%c\n", x, y);v[x].push_back(y);du[y]++;for (int j = 'A'; j <= 'Z'; j++)du2[j] = du[j];int ans = topo_sort(cag);//printf("%d %d\n", i, ans);if (ans == -1)//矛盾{printf("Inconsistency found after %d relations.\n", i);return 0;}else if (cag==n && ans == 1)//排序完了{printf("Sorted sequence determined after %d relations: ", i, res);for (int j = 1; j <= n; j++) printf("%c", res[j]);printf(".\n");return 0;}}printf("Sorted sequence cannot be determined.\n");return 0;
}

车站分级

题目链接:[NOIP2013 普及组] 车站分级 - 洛谷

    这一题放在这里就是因为我觉得这一题就比较像是上一题排序的变形,从题目给出条件来看,车站经过的所有车站只要没有停,那么这个车站一定比停过的车站等级都要低,所以给出一个序列之后,比如1,3,设dj[i]为车站i的等级,那么就隐含了dj[1]>dj[2],dj[3]>dj[2],那么把所有的序列都转化为不等式,那么这一题就跟上一题一样了。需要注意的就是这一题需要统计的数量就是有多少层,每次找完一轮,度为0的都算作一层,相当于这些车站之间没有大小关系,但是跟不同层的是有前后关系的。

#include
#include
#include
#include
using namespace std;
#define N 1001
bool flag[N][N];//标记这条边flag[x][y]x是否已经建立和y的关系
vectorv[N];
int n, m,ans;
bool vis[N];
int du[N];
int Min = 0x3f3f3f, Max = -0x3f3f3f;
int a[N];//存储车道序列和后面暂时存放度0的点
void topo()
{//要计算有多少层,每一次找完一轮有几个度为0,那么这一次找到的都是算作一层//先存储起来,然后逐个减度int all_num=Max-Min+1;//这一轮找到的个数和总个数while (all_num){int num = 0;//for (int i = Min; i <= Max; i++)//	printf("du[i]=%d\n", du[i]);for (int i = Min; i <= Max; i++){//printf("ans=%d\n", ans);if (!vis[i] && !du[i]){a[++num] = i;all_num--;vis[i] = 1;}}ans++;//一层//printf("all_num=%d\n", all_num);for (int i = 1; i <= num; i++){int x = a[i];for (int j = 0; j < v[x].size(); j++)du[v[x][j]]--;}}
}int main()
{scanf("%d%d", &n, &m);int t, x;for (int i = 1; i <= m; i++){scanf("%d", &t);for (int i = 1; i <= t; i++){scanf("%d", a+i);vis[a[i]] = 1;}//printf("t=%d\n", t);Min = min(Min, a[1]);Max = max(Max, a[t]);for (int i = a[1]; i <= a[t]; i++){if (!vis[i])//表示没有出现过,这个点要比所有出现过的点要小{//建边for (int j = 1; j <= t; j++){if (!flag[i][a[j]])//如果没有建过边{flag[i][a[j]] = 1;v[i].push_back(a[j]);du[a[j]]++;}}}}//一条车道建立完毕for (int i = a[1]; i <= a[t]; i++)vis[i] = 0;}//printf("%d %d\n", Min, Max);topo();printf("%d\n", ans);return 0;
}

 就先写到这么多吧。

 

 

相关内容

热门资讯

肩周炎有什么症状? 肩周炎有什么症状?肩周炎起病一般较为缓慢,病程较长,病史多在几个月甚至1~2年,临床以肩痛、肩关节功...
您好!我们公司是机械自动化设备... 您好!我们公司是机械自动化设备公司,ISO 质量管理体系有哪些流程?谢谢!建议采用其中的iso900...
准备参加2016年专利代理人考... 准备参加2016年专利代理人考试、请问网上流传的音频怎么好多都是2012年左右的、听那些有问题吗?如...
遍地矿老板,煤炭之后又是天然气... 遍地矿老板,煤炭之后又是天然气,为何上苍如此厚爱山西?因为在很早的时候,山西的植被是非常丰富的,这些...
当红的六大明星偶像团体,你最喜... 当红的六大明星偶像团体,你最喜欢哪一个SHE 少女时代 小虎队 Westlife Candee Ca...
小学生应该有那些 小学生应该有那些听话,活跃,自主学生应该有一年级 二年级 三年级 四年级 五年级 六年级。一年级小学...
途锐为什么这么贵 途锐为什么这么贵途锐样子难看不说 还比什么宝马的越野车贵 为什么这么多人买性能好,它是纯进口车,德...
为什么都说家长才是孩子最好的老... 为什么都说家长才是孩子最好的老师呢?因为家长可以教给孩子很多的东西,孩子的一些行为家长也会进行模仿,...
清华一保洁阿姨弹奏《我的中国心... 清华一保洁阿姨弹奏《我的中国心》惊艳全网,你对此有何感触?我感觉特别厉害,感觉清华北大简直是藏龙卧虎...
求推荐比较好的心理咨询平台 求推荐比较好的心理咨询平台很多吧,例如:韩非-走出焦虑风暴,曾奇峰-小小糖,武志红等等,都是一些有名...
长恨歌是谁写的? 长恨歌是谁写的?白居易-v-长恨歌是白居易写的
内向老实人跟二婚带儿子的女人结... 内向老实人跟二婚带儿子的女人结婚 刚开始那个女的对他很主动 婚后对他态度冷淡 他一心照顾她儿子?通过...
讳疾忌医这个成语的意思是什么呢... 讳疾忌医这个成语的意思是什么呢?  讳疾忌医  【拼音】: huì jí jì yī  【解释】: ...
绿宝石的鲤鱼王放到怪兽饲育屋里... 绿宝石的鲤鱼王放到怪兽饲育屋里升到20级能进化成暴鲤龙吗?绿宝石的鲤鱼王放到怪兽饲育屋里升到20级能...
君子好逑的剧情 君子好逑的剧情谁有电视剧 君子好逑 的剧情啊?最后铁中玉是不是和水冰心结婚了?你要自己想不要什么都问...
怎么安慰离婚的女人? 怎么安慰离婚的女人?不要安慰,没有必要,既然她选择了离婚,就是看清了看淡了,你去安慰,反而让对方不舒...
适合女生看的搞笑电影 适合女生看的搞笑电影八面玲珑的申小姐 美女的烦恼 辣妈辣妹 我生命中最糟糕的男人 我的双面女友 我的...
我要徒劳的寒鸦,农夫与蛇和狼和... 我要徒劳的寒鸦,农夫与蛇和狼和七只小羊的好词,好句和读后感★怎样写读后感:  读后感就是读了一本书,...
十篇两百个单词的趣味故事,加翻... 十篇两百个单词的趣味故事,加翻译。这故事说明,明显的罪状是无法隐瞒的。 The Miser守财奴 A...
十二星座,什么星座是情感的专家... 十二星座,什么星座是情感的专家?貌似是巨蟹座吧。因为他们天生李白。而且具有丰富的情感经验和情感认识。...