51Nod2670还原竞赛图思维+传递闭包

Posted hesorchen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51Nod2670还原竞赛图思维+传递闭包相关的知识,希望对你有一定的参考价值。

题目

2670 还原竞赛图

一张完全无向图,给出每个点的出度,要对每条边定向,求可以互相到达的点对数量。保证答案存在且唯一。

求解

题目保证答案存在且唯一,那么就保证了 s u m a i = n ∗ ( n − 1 ) 2 sum_{a_i}=\\frac {n*(n-1)}{2} sumai=2n(n1)

需要注意的是,对某条边定向的时候,需要考虑,这样会不会导致后面的点的出度无法满足。

代码

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

const int N = 110;
int out[N];
int mp[N][N];
bool vis[N][N];
int in[N];

int main()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> out[i];
    for (int i = 1; i <= n; i++)
    {
        int tmp = out[i];
        for (int j = 1; tmp && j <= n; j++)
        {
            if (i == j)
                continue;
            if (!vis[i][j] && (n - 1) - in[j] - out[j] > 0)
            //保证这条边还没用过,并且用了也不会导致后面的边无法使用
            {
                in[j]++;
                tmp--;
                mp[i][j] = 1;
                vis[i][j] = vis[j][i] = 1;
            }
        }
    }
    for (int i = 1; i <= n; i++)
        mp[i][i] = 1;
    for (int k = 1; k <= n; k++)
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                if (mp[i][k] && mp[k][j])
                    mp[i][j] = 1;
    int ans = 0;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            ans += mp[i][j];
    cout << ans << endl;
    return 0;
}

以上是关于51Nod2670还原竞赛图思维+传递闭包的主要内容,如果未能解决你的问题,请参考以下文章

最短路合集(分层图最短路传递闭包路径还原k短路...)

51Nod1231 记分牌 动态规划

51nod 1231 记分牌

51nod 1272 思维/线段树

51Nod 1241 特殊的排序 —— 思维DP

51nod1201_dp思维题