zoukankan      html  css  js  c++  java
  • 大红数星星 图论 XD网络赛

    问题 A: 大红数星星

    时间限制: 3 Sec  内存限制: 128 MB
    提交: 1066  解决: 67
    [提交][状态][讨论版]

    题目描述

    “三角形十分的美丽,相信大家小学就学过三角形具有稳定性,三角形也是二维几何中最基本的必不可少的元素之……”,大红走在路上若有所思,突然抬头看到了天空中有很多很亮的星星划过,星星和他们划过的轨迹像极了一个无向图。于是好学的大红,就开始数起了“三角形”,1、2、3……数了好久,大红数的眼泪都掉下来了,所以他哭着请求你来帮他,你这么好心一定不会拒绝吧!大红的三角形的定义:如果存在这样的三个边(A,B)、(B,C)、(A,C)(无向边),则算一个三角形。
    大红会告诉你这个图G=(V,E),点数(星星个数)n和边数(轨迹个数)m以及每条边的两个点。

    两个三角形不同是:当对于两个三角形的边,某个三角形存在一条边在另一个三角形的边中无法找到!

    输入

    多组数据。
    第一行一个整数T<=10表示数据组数。
    对于每组数据的第一行n表示星星个数,m表示星星划过的轨迹的个数,
    接下来m行表示每个星星划过的轨迹的端点x,y(1<=x,y<=n)。
    1<=n<=100000,1<=m<=min(100000,n*(n-1)/2)

    输出

    对于每组数据输出一个整数,表示三角形的个数。

    样例输入

    1
    3 3
    1 2
    2 3
    1 3
    

    样例输出

    1
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<sstream>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<cmath>
    #include<map>
    #include<set>
    #include<fstream>
    #include<memory>
    #include<string>
    using namespace std;
    typedef long long LL;
    #define MAXN  100003
    #define INF 1000000009
    /*
    寻找三角形的个数
    思路:
    1. 枚举所有边,然后枚举边上两个点中度比较小的 那个点中包含可以到达 枚举的边中另一点的边 +1 
    最后/3
    2. 先把所有点按照度的大小排序,然后用数组记录一个点可以到达的顶点(要求顶点的度大于它)
    然后枚举每条边,找两个顶点的公共元素数目
    */
    vector<int> E[MAXN];
    vector<int> cnt[MAXN];
    struct edge
    {
        int f, t;
    };
    int T, n, m;
    vector<edge> a;
    int main()
    {
        edge tmp;
        int f, t;
        scanf("%d", &T);
        while (T--)
        {
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; i++)
            {
                E[i].clear();
            }
            a.clear();
            int sum = 0;
            for (int i = 0; i < m; i++)
            {
                scanf("%d%d", &tmp.f, &tmp.t);
                E[tmp.f].push_back(tmp.t);
                E[tmp.t].push_back(tmp.f);
                a.push_back(tmp);
            }
            for (int i = 1; i <= n; i++)
            {
                sort(E[i].begin(), E[i].end());
            }
            for (int i = 1; i <= n; i++)
            {
                for (int j = 0; j < E[i].size(); j++)
                {
                    if (E[E[i][j]].size() > E[i].size())
                        cnt[i].push_back(E[i][j]);//可以到达的顶点 在这里保证顶点的度大于它的度
                }
            }
            for (int i = 0; i < m; i++)//枚举所有边,找两个顶点的公共点个数 
            {
                
                f = a[i].f, t = a[i].t;
                int s1 = E[f].size(), s2 = E[t].size();
                int z = 0, y = 0;
                while (z < s1&&y < s2)
                {
                    if (E[f][z] < E[t][y])
                    {
                        z++;
                    }
                    else if (E[f][z] > E[t][y])
                    {
                        y++;
                    }
                    else
                    {
                        z++; y++; sum++;
                    }
                }
            }
            printf("%d
    ", sum / 3);
        }
    }


  • 相关阅读:
    1065-两路合并
    1064-快速排序
    1063-冒泡排序
    1062-直接插入排序
    1061-简单选择排序
    1058-Tom and Jerry
    关于WinForm引用WPF窗体
    ref与out的区别
    看到他我一下子就悟了(续)---委托
    域名的a记录转过来他的公网ip
  • 原文地址:https://www.cnblogs.com/joeylee97/p/6813663.html
Copyright © 2011-2022 走看看