Jzoj P4269 挑竹签___拓扑排序

题目大意:

n 个竹签,有 m 组限制关系 x i , y i ,表示竹签 x i 压着 y i ,问在不影响平衡的情况下,你最多能连续拿出多少个竹签。

1 <= n , m <= 1 000 000

分析:

把限制关系 x i , y i ,变成一条 x i > y i 的有向边,
那么就是直接拓扑排序即可,
拓扑排序是这样一个东西:
①找入度为 0 的点加入队列
②并将所有与这个点有关的连边删去
③重复①②
那么你将所有进过队列的点统计一下数目即可。
因为每次你入度为 0 就是你没有被别的竹签限制

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define N 1000005

using namespace std;

queue <int> Q;
struct Node { int To, nxt; }e[N];
int Rd[N], ls[N], n, m, cnt, ans;

void Addedge(int u, int v) {
    e[++cnt].To = v, e[cnt].nxt = ls[u], ls[u] = cnt;   
}

void Top_sort() {
    for (int i = 1; i <= n; i++) 
         if (!Rd[i]) ans++, Q.push(i);
    while (!Q.empty()) {
           int u = Q.front();
           Q.pop();
           for (int i = ls[u]; i; i = e[i].nxt) {
                int v = e[i].To;
                if (!(--Rd[v])) ans++, Q.push(v);
           }
    }
}

int main() {
    freopen("mikado.in", "r", stdin);
    freopen("mikado.out", "w", stdout);
    scanf("%d %d", &n, &m);
    int u, v;
    for (int i = 1; i <= m; i++) {
         scanf("%d %d", &u, &v);
         Addedge(u, v), Rd[v]++;
    }
    Top_sort();
    printf("%d\n", ans);
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/gx_man_vip/article/details/81021895
今日推荐