• CSU 1802 小X的战斗力【拓扑dp】


    题目链接

    题意:n个人,每个人有一个能力值。给出m组关系A, B, 表示A的能力值大于B的能力值。

    问:m组关系中是否有自相矛盾的?若不矛盾,问:第1个人在所有人的能力值中排名第几?有多少人的能力值的排名可以确定?

    题解:拓扑排序。存两个图,原图与反图。

    若原图可达该点数+反图可达该点数-1 = n,则排名确定。

    bitset一下。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define X first
     4 #define Y second
     5 #define pii pair<int, int>
     6 #define mp make_pair
     7 typedef long long ll;
     8 
     9 vector<int> ve[155], rve[155];
    10 int in[155], rin[155];
    11 bitset<155> dp[155], rdp[155];
    12 int ra[155], rra[155];
    13 int topsort(int n, int* in, vector<int>* ve, bitset<155>* dp, int* ra){
    14     queue<int> Q;
    15     for(int i = 1; i <= n; i++)
    16         if(in[i] == 0) Q.push(i);
    17     int ret = 0;
    18     while(!Q.empty()){
    19         int p = Q.front();
    20         Q.pop();
    21         ret++;
    22         ra[p] = ret;
    23         for(int i = 0; i < ve[p].size(); i++){
    24             int to = ve[p][i];
    25             in[to]--;
    26             dp[to] |= dp[p];
    27             if( !in[to] ) Q.push(to);
    28         }
    29     }
    30     return ret == n;
    31 }
    32 void debug(int n){
    33     puts("*******************");
    34     for(int i = 1; i <= n; i++){
    35         cout << i << endl;
    36         cout << dp[i] << ' ' << rdp[i] << endl;
    37     }
    38     puts("********end********");
    39 }
    40 int main(){
    41     int t; scanf("%d", &t);
    42     while(t--){
    43         int n, m, u, v;
    44         scanf("%d%d", &n, &m);
    45         for(int i = 1; i <= n; i++){
    46             ve[i].clear();
    47             rve[i].clear();
    48             in[i] = rin[i] = 0;
    49             ra[i] = rra[i] = 0;
    50             dp[i].reset(), rdp[i].reset();
    51             dp[i][i-1] = rdp[i][i-1] = 1;
    52         }
    53         for(int i = 0; i < m; i++){
    54             scanf("%d%d", &u, &v);
    55             ve[u].push_back(v);
    56             in[v]++;
    57             rve[v].push_back(u);
    58             rin[u]++;
    59         }
    60 
    61         if( !topsort(n, in, ve, dp, ra) )//有向图有环
    62             puts("Wrong");
    63         else{
    64             topsort(n, rin, rve, rdp, rra);
    65             //前面有 dp[i]-1 个, 后面有 rdp[i]-1 个;
    66             printf("%d
    ", dp[1].count()+rdp[1].count()-1 == n? ra[1]:-1);
    67             int sum = 0;
    68             for(int i = 1; i <= n; i++)
    69                 if(dp[i].count()+rdp[i].count()-1 == n) sum++;
    70             printf("%d
    ", sum);
    71         }
    72     }
    73     return 0;
    74 }
    View Code

     另解:floyd

  • 相关阅读:
    判断数组的方法
    介绍下 npm 模块安装机制,为什么输入 npm install 就可以自动安装对应的模块?
    因为这样那样的原因又滚回来了
    AFO成功
    SDOI2018
    TJOI2018
    杂题
    线段树合并
    几个dp的陈年老题
    【自家测试】2018-5-9
  • 原文地址:https://www.cnblogs.com/dirge/p/5986437.html
Copyright © 2020-2023  润新知