zoukankan      html  css  js  c++  java
  • 洛谷 P1983 车站分级

    这是一道存图+拓扑排序的题,但是看了一晚上好像只看出存图来....

     

     

    下面说一下自己的理解的思路:

     

    首先对这个题要有正确的理解:  

    1.  给出的一趟车,它所停靠的站点一定 >= 它所经过站点中级别最小的点一定 >= 起始点和终点;

    2.  所有停靠的点的级别一定 > 未停靠的点;

    3.  根据大于关系建立有向无环图(DAG) ,拓扑排序

     

     

    所以,这道题的鬼畜之一在于——建图:

    不是将火车停靠的车站与下一个停靠车站之间建图,而是将没停靠的站点与其下一个停靠的车站构造一个有向无环图(因为没停靠的车站的级别一定比停靠的车站的级别要低...

     

    这道题的鬼畜之二在于一个优化:

    实际上有最坏的情况,就是两个点之间连了很多条边(因为有很多趟车,不同趟的车可能经过相同的站点),容易炸空间,所以就用vis数组进行标记,来简化空间复杂度.....

     

    所以,这道题的思路可分为:

     

    优化读入----->建图+vis优化------>拓扑排序-------->输出答案

    下面是AC代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 
     5 using namespace std;
     6 
     7 inline int get_num() {//读入优化 
     8     int num = 0;
     9     char c = getchar();
    10     while (c < '0' || c > '9') c = getchar();
    11     while (c >= '0' && c <= '9')
    12         num = num * 10 + c - '0', c = getchar();
    13     return num;
    14 }
    15 
    16 const int maxn = 1005;
    17 
    18 int graph[maxn][maxn], ind[maxn], stop[maxn], vis[maxn], level[maxn];
    19 //graph存图,ind存点的入度,stop存车站,vis是否访问(一个优化),level存车站的级别 
    20 queue<int> q;
    21 
    22 int main() {
    23     int n = get_num(), m = get_num(), ans = 0;
    24     for (int i = 1; i <= m; ++i) {
    25         int s = 0, t = 0, cnt = get_num();
    26         memset(stop, 0, sizeof(stop));
    27         memset(vis, 0, sizeof(vis));
    28         for (int j = 1; j <= cnt; ++j) {
    29             if (j == 1) vis[s = stop[j] = get_num()] = 1;//起点车站 
    30             else if (j == cnt) vis[t = stop[j] = get_num()] = 1;//终点车站 
    31             else vis[stop[j] = get_num()] = 1;//一般车站 
    32         } 
    33         for (int j = 1; j <= cnt; ++j) { 
    34             for (int k = s; k <= t; ++k)
    35                 if (!vis[k] && !graph[k][stop[j]])//k车站没经过并且还没与车站j连成图 
    36                     graph[k][stop[j]] = 1, ++ind[stop[j]];//构建有向无环图,j站入度+1 
    37         }
    38     }
    39     for (int i = 1; i <= n; ++i)
    40         if (!ind[i]) { //没有入度
    41             level[i] = 1;//将级别设为1 
    42             q.push(i);//入队,准备拓扑排序 
    43         }
    44     while (!q.empty()) {
    45         int u = q.front();//取队首 
    46         q.pop();
    47         for (int v = 1; v <= n; ++v)//遍历 
    48             if (graph[u][v]) {//如果u点与v点有一条边 
    49                 if (level[v] < level[u] + 1)
    50                     level[v] = level[u] + 1;//更新操作,因为所要到达的车站一定比前面那个没有到达的车站的级别要高 
    51                 if (!(--ind[v])) q.push(v);//toposort核心(判断入度,并入队 
    52             }
    53         if (ans < level[u]) ans = level[u];//更新答案
    54     }
    55     printf("%d", ans);
    56     return 0;
    57 }

    难点在于建图,真搞不懂是如何想到这样建图的!!!

     

    toposort也很重要!!!

     

  • 相关阅读:
    如何:创建自定义 HTTP 模块
    [转]开源邮件系统
    [转]开源.NET邮件服务器
    [转]文件上传及图片水印
    oracle存储过程学习收集|韩顺平oracle视频教程|
    PLSQL自动输入select * from|附件在cnblogs文件|
    oracle有规律数据触发器实现递增(NC地区分类)|更新一路case简化|
    oracle中的几种循环|转|
    官方解释sqlplus /nolog conn /as sysdba无密码可登陆
    建工项目对账查询引擎sql
  • 原文地址:https://www.cnblogs.com/New-ljx/p/10498483.html
Copyright © 2011-2022 走看看