拓扑排序以及C++读取空行[算法学习日常1/100]

拓扑排序以及C++读取空行[算法学习日常1/100]

算法学习日常第一天

2019年8月2日

  • 今天上午,重新认识算法的全貌各种资源及知识点总结

  • 并且还了解到了常见错误写法,当然自己当年也写过很多错误

  • 下午先是补牛客5的多校G题的dp–接着昨天的补都补了90mins(含对着手写第一遍),还是太菜了

  • 然后补H题,发现自己昨天写了3个小时的这个题目不是字符串插入题…而是一个拓扑排序题..真的自己菜得可怕..写错分类怎么可能做对,然后自己又焦虑了很久,知道2019年8月2日15:48:15才静下来认真地学习拓扑排序
    • 拓扑排序在紫书上学了下,就是把点对关系看成一个图里面的指向关系,即把每一个点对看做小数指向大数的有向边,如果图没有有向环的话,说明是可以的,否则是不行的
    • 记自己头铁处理空行读入,搞了整整一个小时读取空行

拓扑排序以及空行头铁见代码

/*
2019年8月2日19:25:05
拓扑排序bfs

拓扑排序算法思想
1、在AOV网络中选一个没有直接前驱的顶点, 并输出之;
2、从图中删去该顶点, 同时删去所有它发出的有向边;--->(我下面的题目使用stop实现删除)
3、重复以上步骤, 直到
◆ 全部顶点均已输出,拓扑有序序列形成,拓扑排序完成;
◆ 或者图中还有未输出的顶点,但已跳出处理循环。这说明图中还剩下一些顶点,
它们都有直接前驱,再也找不到没有前驱的顶点了。这时AOV网络中必定存在有向环。
*/
#include<bits/stdc++.h>
using namespace std;
const int M = 1e4+5;
int n,m,lentmp;
string s[10][10];
/*用string本来可以不用下面的len*/
int len[10][10];
int it[10][10];
string ans,t;
bool check();
bool solve();

int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    cin>>n>>m;
    for(int i=0;i<m*(m-1)/2;i++){
        cin>>t>>lentmp;
        int x=t[0]-'a',y=t[1]-'a';
        if(x>y) swap(x,y);
        len[x][y] = lentmp;
        // if(lentmp) cin>>s[x][y];
        /*我的头铁(~~比赛因此卡1小时去谷歌~~)写法
        先直接用cin.get()吃掉t和lentmp后面的回车
        再getline(),
        否则getline会吃那个回车而导致少读数据*/
        cin.get();
        getline(cin,s[x][y]);
    }
    if(!solve()) puts("-1");

    return 0;
}

/*暴力检测每队关系是否和整个串中的样子是一样的
法二: 也可以每一对关系得到一个ans的tmp串,然后再去==判断
      但是效率低
*/
bool check(){
    for(int i=0;i<m;i++){
        for(int j=i+1;j<m;j++){
            int now = 0;
            for(int k=0;k<n;k++){
                if(ans[k]=='a'+i||ans[k]=='a'+j){
                    if(ans[k]!=s[i][j][now]) return 0;
                    now++;
                }
            }
            if(now!=len[i][j]) return 0;
        }
    }
    return 1;
}

bool solve(){
    for(int i=0;i<n;i++){
        /* 这里是每个大串的排序关系-通过m次的关系问询确定的

        注意前面巧妙地处理出了j小于k--->这就是拓扑排序的思路

        1.对没有出现过的关系(即s[j][k]的那一维全为空)stop[j]和stop[k]全都赋值为1
        2.对于到最后了的关系(即s[j][k][]='\0')全赋空


        因为有m*(m-1)/2 对 关系,也就是每两个都有比较,所以一定能够得出最前面的一个字符..所以就完美了!

        这里每次stop都会清零!*/
        bool stop[10] = {};
        for(int j=0;j<m;j++){
            for(int k=j+1;k<m;k++){
                if(!s[j][k][it[j][k]]) stop[j]=stop[k]=1;
                else if(s[j][k][it[j][k]]=='a'+j) stop[k]=1;
                else stop[j] = 1;
            }
        }
        bool done = false;
        for(int j=0;j<m;j++){
            if(!stop[j]){
                ans+='a'+j;
                for(int k=0;k<m;k++){
                    if(k<j) it[k][j]++;
                    else if(k>j) it[j][k]++;
                }
                done = true;
                break;
            }
        }
        if(!done) return 0;
    }
    if(!check()) return 0;
    cout<<ans<<endl;
    return 1;
}
  • 晚上成功补完H题和I题,发现好像没有时间补B题了,明天上午来补一下B题

每日一句叨叨

杜月笙知道成功需要代价,他想为自己洗白(小时候家里穷只能混黑帮),为整个帮派洗白,但穿了大半辈子长褂(为了不露出纹身),让自己的说书先生给自己讲了大半辈子学,也为上海的繁荣安定做了大半辈子贡献,但却最终未被认可(通过人脉被选之为一个参议长,但蒋介石让他自己退位),但杜月笙却永远被后人被历史铭记

若命运不公,那就和它斗到底!

打赏 赞(0)
微信
支付宝
微信二维码图片

微信扫描二维码打赏

支付宝二维码图片

支付宝扫描二维码打赏

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

发表评论

电子邮件地址不会被公开。 必填项已用*标注