2.1 题目描述

给定一个无自环重边的无向图,求这个图的三元环1的个数以及补图2的三元环个数。

2.2 输入格式

第一行 2 个数 n, m ,分别表示图的点数、边数。

接下来 m 行,每行两个数 u, v ,表示一条连接 u, v 的无向边。

2.3 输出格式

一行两个数,依次表示原图的三元环个数以及补图的三元环的个数。

2.4 样例输入

5 5

1 2

1 3

2 3

2 4

3 4

2.5样例输出

2 1

2.6数据范围

对于 30% 的数据:n ≤ 100

对于 60% 的数据:m ≤ 500

对于 100% 的数据:n ≤ 10^5 , m ≤ 10^5

2.7评分方式

如果你两个数均输出正确,得 10 分。

否则如果两个数中任意一个正确或者两个数的和正确,得 6 分。 否则不得分。

1大小为 3的环。即一个无序三元组 (x, y, z) 使得任意两点之间都有边

2一条连接(u, v)(u = v) 的边,如果在原图中出现了,那么在补图中不会出现,否则一定会在补图中出现。

题解

题目中说两个数的和正确可以得分,是不是说明先求和是一个突破口呐?

对于一个完全图,三元环的数量是C(n,3),少了一些边,就少了一些三元环,少的三元环应该有至少一条边在原图中,至少一条边在补图中。

减少的三元环数量为:sigma(d[i]*(n-1-d[i]))/2 (d[i]为度数)

一开始我想不通为什么是除以2,然后我画了两个图,就发现了答案,每个三元环可以被两个点找到。

剩下的就是求原图中的三元环,有一个神奇的算法,和分段暴力有一丢丢类似吧。

将所有点分成两类:d[i]<sqrt(m)的和d[i]>sqrt(m)的.

先求包含第一类点的三元环个数. 由于边很少,所以枚举2条边即可.由于一个点的度不超过sqrt(m),所以一条边最多被枚到(sqrt(m))次,最多枚M条边,所以这个操作时O(m*sqrt(m))的.

再求不包含第一类点的三元环个数. 由于每条边贡献2个度,所以二类点的数量是O(sqrt(m))级的.直接枚举三个点,复杂度O((sqrt(m))^3)=O(m*sqrt(m))

所以算法总的复杂度是O(m*sqrt(m))的.

我先用了一个vector来判断点i与j是否有边,但是T掉了,然后get到了一个聪明的把一条边的两个节点一起hash的方法,就写了一个hash表水过去了。

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<set>
#define nn 100010
#define mod 1000007
#define base 2333
using namespace std;
namespace fastIO
{
#define buf_size 100000
bool error;
inline char gc()
{
static char buf[buf_size + 1],*l=buf,*r=buf;
if(l==r)
{
l=buf;
r=buf+fread(buf,1,buf_size,stdin);
if(l==r) {error = 1;return -1;}
}
return *l++;
}
inline bool blank(char ch) {return ch=='\n'||ch =='\t'||ch ==' '||ch =='\r'||error;}
inline bool getint(int &x)
{
char ch; int f = 1;
while (blank(ch = gc())); if (error) return false;
x = 0;
if (ch == '-') f=-1,ch=gc();
while (1){x = (x<<1) + (x<<3)+ch-'0';if(!isdigit(ch = gc())) break;}
x*=f;
return true;
}
inline void putint(long long x)
{
if(!x) {putchar('0'); return;}
if(x<0){x=-x; putchar('-');}
static int out[13];
register int len = 0;
while(x){out[++ len]=x%10; x/=10;}
while(len) putchar(out[len --]+'0');
}
#undef buf_size
}
using namespace fastIO;
int in[nn],fir[nn],nxt[nn<<1],to[nn<<1],a[1000007],b[1000007],head[1000007],next[1000007];
bool hash[1000007];
int e=0,inum=0;
void add(int u,int v)
{
nxt[++e]=fir[u];fir[u]=e;to[e]=v;
nxt[++e]=fir[v];fir[v]=e;to[e]=u;
}
long long c(long long n,int m)
{
long long an=(n-2)*(n-1)*n/6;
return an;
}
void addd(int u,int v)
{
int t=(u*base+v)%mod;
a[++inum]=u;b[inum]=v;next[inum]=head[t];head[t]=inum;
}
inline bool query(int u,int v)
{
int t=(u*base+v)%mod;
for (int p=head[t];p;p=next[p])
if (a[p]==u&&b[p]==v)
return 1;
return 0;
}
int main()
{
freopen("triangle.in","r",stdin);
freopen("triangle.out","w",stdout);
int n,m,u,v;
getint(n);getint(m);
long long all=0,sum=0;
for(register int i(1);i<=m;i++)
{
getint(u);getint(v);
addd(u,v);
add(u,v);
in[u]++;in[v]++;
}
for(register int i(1);i<=n;i++)
all+=in[i]*(n-1-in[i]);
all/=2;
all=c(n,3)-all;
for(register int i(1);i<=n;i++)
{
for(register int j=fir[i];j;j=nxt[j])
for(register int k=nxt[j];k;k=nxt[k])
{
if(query(to[j],to[k])||query(to[k],to[j]))
sum++;
}
}
putint(sum/3);putchar(' ');putint(all-sum/3);
return 0;
}

∆ (triangle)的更多相关文章

  1. [LeetCode] Triangle 三角形

    Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent n ...

  2. [LeetCode] Pascal's Triangle II 杨辉三角之二

    Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3,Return [1,3, ...

  3. [LeetCode] Pascal's Triangle 杨辉三角

    Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,Retur ...

  4. 【leetcode】Pascal's Triangle II

    题目简述: Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3, Retur ...

  5. 【leetcode】Pascal's Triangle

    题目简述: Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5 ...

  6. POJ 1163 The Triangle(简单动态规划)

    http://poj.org/problem?id=1163 The Triangle Time Limit: 1000MS   Memory Limit: 10000K Total Submissi ...

  7. Triangle - Delaunay Triangulator

    Triangle - Delaunay Triangulator  eryar@163.com Abstract. Triangle is a 2D quality mesh generator an ...

  8. LeetCode 118 Pascal's Triangle

    Problem: Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows  ...

  9. LeetCode 119 Pascal's Triangle II

    Problem: Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3,Ret ...

  10. 【leetcode】Triangle (#120)

    Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent n ...

随机推荐

  1. NOIP模拟17.10.12

    T1 临江仙 旧梦 题目背景 闻道故园花陌,今年奼紫嫣红.扬帆直渡水千重.东君何解意,送我一江风. 还是昔时庭院,终得醉卧花丛.残更惊醒月明中.流光如旧岁,多少梦成空. 题目描述 #define go ...

  2. Leetcode77. Combinations组合

    给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合. 示例: 输入: n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3] ...

  3. Git pull 强制覆盖本地文件 - CSDN博客

    Git pull 强制覆盖本地文件 原创 2015年11月16日 22:07:56 标签: git git fetch --all git reset --hard origin/master git ...

  4. Faster RCNN算法训练代码解析(1)

    这周看完faster-rcnn后,应该对其源码进行一个解析,以便后面的使用. 那首先直接先主函数出发py-faster-rcnn/tools/train_faster_rcnn_alt_opt.py ...

  5. 【JZOJ5093】【GDSOI2017第四轮模拟day3】字符串匹配 哈希

    题面 对于一个字符集大小为C的字符串P,我们可以将任意两种字符在P中的位置进行互换,例如P=abcba,我们交换a,b就变为bacab,交换a,d就变为dbcbd,交换可以进行任意次.若交换后P变为了 ...

  6. js数组求交集

    求两个数组的交集 var arr1 = [1,2,3]; var arr2 = [2,3,4]; var arr3; arr3 = arr1.filter(function(num) { return ...

  7. python中sort排序

    排序并且改变自身结果: nums.sort()

  8. SPSS分析技术:无序多元Logistic回归模型;美国总统大选的预测历史及预测模型

    SPSS分析技术:无序多元Logistic回归模型:美国总统大选的预测历史及预测模型 在介绍有序多元Logistic回归分析的理论基础时,介绍过该模型公式有一个非常重要的假设,就是自变量对因变量多个类 ...

  9. 【python小随笔】函数的初始化与私有化

    1:初始化 class test(object): def __init__(self,name):#初始化函数 self.name = name#构造初始化一个变量为类的全局变量, 类的所有函数都可 ...

  10. 数据分析1:安装tushare安装包

    1. 2. 3.重点内容