CodeVS 2833 奇怪的梦境(拓扑排序)

原题目:

题目描述 Description
Aiden陷入了一个奇怪的梦境:他被困在一个小房子中,墙上有很多按钮,还有一个屏幕,上面显示了一些信息。屏幕上说,要将所有按钮都按下才能出去,而又给出了一些信息,说明了某个按钮只能在另一个按钮按下之后才能按下,而没有被提及的按钮则可以在任何时候按下。可是Aiden发现屏幕上所给信息似乎有矛盾,请你来帮忙判断。
输入描述 Input Description
第一行,两个数N,M,表示有编号为1…N这N个按钮,屏幕上有M条信息。
接下来的M行,每行两个数ai,bi,表示bi按钮要在ai之后按下。所给信息可能有重复,保证ai≠bi。
输出描述 Output Description
若按钮能全部按下,则输出“o(∩_∩)o”。
若不能,第一行输出“T_T”,第二行输出因信息有矛盾而无法确认按下顺序的按钮的个数。输出不包括引号。
样例输入 Sample Input
3 3
1 2
2 3
3 2
样例输出 Sample Output
T_T
2

┄┅┄┅┄┅┄┅┅┄┅┄┅┄┅┅┄┅┄┅┄┅┅┄┅┄┅┄┅┅┄┅┄┅┄┅┅┄┅┄┅┄┅┅┄┅┄┅┄┅┅┄┅┄┅┄┅┅┄┅┄┅┄┅┅┄┅┄┅┄┅┄°

CodeVS 2833 奇怪的梦境(拓扑排序)

分类:【拓扑排序】
思路:进行拓扑排序,排序成功则输出,若失败则输出 总结点数 - 已拓扑的结点个数。

都是很久以前写的东西了,也懒得再回想了,直接把代码丢上来。

版本1:前向星优化版拓扑排序 78ms 748 kB

#include <bits/stdc++.h>
using namespace std;
#define MAXN 10005

struct Node {
    int v;
    int next;
};
Node edge[MAXN * 4];
int head[MAXN], cnt, deg[MAXN], flag;

void TopSort(int n) {
    priority_queue<int, vector<int>, greater<int> > que;
    for(int i=1; i<=n; i++) {
        if(deg[i] == 0) {
            que.push(i);
            deg[i]--;
        }
    }
    int k = 1;
    while(que.empty() == false) {
        int u = que.top();
        que.pop();
        //放入Top数组,这里不需要所以不写
        flag++;
        for(int i=head[u]; i!=-1; i=edge[i].next) {
            Node e = edge[i];
            deg[e.v]--;
            if(deg[e.v] == 0)
                que.push(e.v);
        }
    }
}

int main()
{
    memset(head, -1, sizeof(head));
    memset(deg, 0, sizeof(deg));
    int n, m, i;
    cin>>n>>m;
    while(m--) {
        int u, v;
        cin>>u>>v;
        for(i = head[u]; i != -1; i = edge[i].next)
            if(edge[i].v == v) break;
        if(i == -1) {
            deg[v]++;
            edge[cnt].v = v;
            edge[cnt].next = head[u];
            head[u] = cnt;
            ++cnt;
        }
    }
    flag = 0;
    TopSort(n);
    if((n-flag) > 0) {
        cout<<"T_T"<<endl;
        cout<<(n-flag)<<endl;
    } else {
        cout<<"o(∩_∩)o"<<endl;
    }
    return 0;
}

版本2: 1511ms 95 MB

#include <bits/stdc++.h>
using namespace std;
#define MAXN 10005
bool G[MAXN][MAXN];
int deg[MAXN], flag, n;

void TopSort() {
    int k;
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= n; j++) {
            if(deg[j] == 0) {
                ++flag;
                deg[j] = -1;
                k = j;
                break;
            }
        }
        for(int j = 1; j <= n; j++) {
            if(G[k][j] == true) {
                G[k][j] = false;
                deg[j]--;
            }
        }
    }
}

int main() {
    memset(deg, 0, sizeof(deg));
    memset(G, false, sizeof(G));
    int M;
    cin >> n >> M;
    while(M--) {
        int u, v;
        cin >> u >> v;
        if (G[u][v] == false) {
            G[u][v] = true;
            deg[v]++;
        }

    }
    flag = 0;
    TopSort();
    if((n - flag) > 0) {
        cout <<"T_T"<<endl;
        cout<<(n - flag)<<endl;
    } else {
        cout<<"o(∩_∩)o"<<endl;
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值