uvalive_6528_Disjoint water supply(DAG)

題目大意

有編號爲1 ~ c 的 c 個點,在點上建有向邊,如果有邊 a -> b ,則a一定小於b。
因此圖爲DAG。
問有多少點對 (a, b),存在兩條路分別從1到達a和b,並且在兩條路上只有1同時出現。
假設1和其他點都滿足條件。

思路

計算所有不滿足條件的點對數。
編號從小到大對點進行標記,如果前驅節點的標號相同,此節點也標記相同的號,如果不同就標記爲自己的序號。
邊界條件:如果前驅節點中有1則標記自己的序號。
標記完後,節點會被分爲若干組,標號的意義是: 此節點通往節點1的多條路徑都必須經過的點。
標號相同的點對一定不滿足條件。
ans = Comb(c, 2) - ∑ Comb(ai, 2)
ai 爲各組的節點數



#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#define INF 0x3f3f3f3f
#define rep0(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)
#define rep_1(i, n) for (int i = n; i > 0; i--)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define mem(x, y) memset(x, y, sizeof(x))

#define MAXN 1010
using namespace std;
typedef long long ll;
vector<int> pre[MAXN];
int cnt[MAXN], bk[MAXN], c, p;
int u, v;
ll comb(int x)
{
    return (ll)x * (x - 1) / 2;
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
    #endif // ONLINE_JUDGE

    while (scanf("%d %d", &c, &p) != EOF)
    {
        mem(cnt, 0);
        mem(bk, 0);
        for (int i = 1; i <= c; i++)
            pre[i].clear();


        for (int i = 0; i < p; i++)
        {
            scanf("%d %d", &u, &v);
            pre[v].push_back(u);
        }
        ll ans = 0;
        for (int i = 2; i <= c; i++)
        {

            for (int j = 0; j < pre[i].size(); j++)
            {
                int fa = pre[i][j];
                if (fa == 1)
                {
                    bk[i] = i;
                    break;

                }
                if (!bk[i])
                    bk[i] = bk[fa];
                else
                {
                    if (bk[i] != bk[fa])
                    {
                        bk[i] = i;
                        break;
                    }

                }




            }
            cnt[bk[i]]++;

        }

        for (int i = 2; i <= c; i++)
        {
            if (cnt[i])
                ans += comb(cnt[i]);
        }





        printf("%lld\n", comb(c) - ans);

    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章