HDU - 6184 C - Counting Stars

  题目大意:有n个点,m条边,问有一共有多少个‘structure’也就是满足V=(A,B,C,D) and E=(AB,BC,CD,DA,AC)这样一个图形,类似于四边形中间连接了一条对角线。

  如果我们把这个四边形拆分的话,其实就是两个共用一条边的三角形,而在图中就是三元环。求三元环有两种求法,个人感觉这个三元环的时间复杂度很玄学。

  第一种一种就是枚举点x,然后枚举和点x相连的y,这时根据y的度,如果y的度小于等于sqrt(m),那么我们可以直接枚举和y相连的z,看z和x是否相连,这时时间复杂度最差是m*sqrt(m),如果y的度大于sqrt(m)的话,说明y有很多点相连,再枚举y的话就会超时,这时枚举再枚举x找z,根据set或者map来判断y和z是否相连,复杂度最差也是m*sqrt(m),详情见代码

 #include<cstdio>
#include<vector>
#include<set>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=;
set<ll> s;
vector<int> vv[N];
int link[N],book[N];
inline void init(int n)
{
s.clear();
for(int i=;i<=n;i++)
{
vv[i].clear();
link[i]=;
book[i]=;
}
}
int main()
{
int n,m,u,v;
while(~scanf("%d%d",&n,&m))
{
init(n);
for(int i=;i<m;i++)
{
scanf("%d%d",&u,&v);
vv[u].push_back(v);
vv[v].push_back(u);
s.insert(1ll*u*(n+)+v);//set保存u和v相连的信息
s.insert(1ll*v*(n+)+u);
}
ll ans=;
for(int x=;x<=n;x++)
{
book[x]=;//每个点只有枚举一遍
for(int i=;i<vv[x].size();i++)
link[vv[x][i]]=x;//记录和x点相连的点
//枚举和x相连的y
for(int i=;i<vv[x].size();i++)
{
int y=vv[x][i],sum=;
if(book[y])
continue;
if(1ll*vv[y].size()*vv[y].size()<=m)
{
//枚举找到和x相连的z
for(int j=;j<vv[y].size();j++)
if(link[vv[y][j]]==x)
sum++;
}
else
{
//枚举找到和y相连的z
for(int j=;j<vv[x].size();j++)
if(s.find(1ll*y*(n+)+vv[x][j])!=s.end())
sum++;
}
ans+=1ll*sum*(sum-)/;//每两个三元环就可以组成一个需要的图形
}
}
printf("%lld\n",ans);
}
return ;
}

暴力m*sqrt(m)

  当然上面那个做法有点类似于暴力,而且前向星建图会超时,不知道为啥子,所以我们还需要第二种方法

  第二种是枚举边,不过得先对边进行处理。也就是统计每个点的度,然后我们根据这个度把之前的双向边变成度数大的点指向度数小的点,度数相同按序号的有向边,这样构成了一个有向无环图。这样我们枚举每条边,统计这条边能构成几个三元环,最后统计答案。但时间复杂度我不懂算,很玄学,比第一种快了不只一倍,并且在建边时用swap会超时。。

 #include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=;
vector<pii> vv[N];
int link[N],line[N],du[N],val[*N],u[*N],v[*N];
inline void init(int n)
{
for(int i=;i<=n;i++)
{
du[i]=;
vv[i].clear();
link[i]=line[i]=;
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
init(n);
for(int i=;i<=m;i++)
{
val[i]=;
scanf("%d%d",&u[i],&v[i]);
du[u[i]]++,du[v[i]]++;
}
for(int i=;i<=m;i++)//按度数改成有向边
{//每条边记录下另一个端点和边的编号
if(du[u[i]]<du[v[i]])
vv[u[i]].push_back(pii(v[i],i));
else if(du[u[i]]>du[v[i]])
vv[v[i]].push_back(pii(u[i],i));
else
{
if(u[i]<v[i])
vv[u[i]].push_back(pii(v[i],i));
else
vv[v[i]].push_back(pii(u[i],i));
}
// 改成swap(u[i],v[i]),然后再建边会超时
}
for(int i=;i<=m;i++)//枚举每条边
{
int x=u[i],y=v[i];
for(int j=;j<vv[x].size();j++)
{//遍历和x相连的z
int z=vv[x][j].first,id=vv[x][j].second;
link[z]=x;//z和x相连
line[z]=id;//记录相连的这条边的编号
}
for(int j=;j<vv[y].size();j++)
{//遍历和y相连的z
int z=vv[y][j].first,id=vv[y][j].second;
if(link[z]==x)
{//如果这个z和x相连的话
val[i]++;
val[id]++;
val[line[z]]++;
//相关的三条边都可以组成了一个三元环
}
}
}
ll ans=;
for(int i=;i<=m;i++)
ans+=1ll*val[i]*(val[i]-)/;
printf("%lld\n",ans);
}
return ;
}

vector建图

 #include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=;
struct Side{
int v,ne;
}S[*N];
int sn,head[N],link[N],line[N],du[N],val[*N],u[*N],v[*N];
inline void init(int n)
{
sn=;
for(int i=;i<=n;i++)
{
head[i]=-;
du[i]=;
link[i]=;
line[i]=-;
}
}
inline void add(int u,int v)
{
S[sn].v=v;
S[sn].ne=head[u];
head[u]=sn++;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
init(n);
for(int i=;i<m;i++)
{
val[i]=;
scanf("%d%d",&u[i],&v[i]);
du[u[i]]++,du[v[i]]++;
}
for(int i=;i<m;i++)
{
if(du[u[i]]<du[v[i]])
add(u[i],v[i]);
else if(du[u[i]]>du[v[i]])
add(v[i],u[i]);
else
{
if(u[i]<v[i])
add(u[i],v[i]);
else
add(v[i],u[i]);
}
}
for(int i=;i<m;i++)
{
int x=u[i],y=v[i];
for(int j=head[x];j!=-;j=S[j].ne)
{
link[S[j].v]=x;
line[S[j].v]=j;
}
for(int j=head[y];j!=-;j=S[j].ne)
{
int z=S[j].v;
if(link[z]==x)
{
val[i]++;
val[j]++;
val[line[z]]++;
}
}
}
ll ans=;
for(int i=;i<m;i++)
ans+=1ll*val[i]*(val[i]-)/;
printf("%lld\n",ans);
}
return ;
}

前向星建图

三元环HDU 6184的更多相关文章

  1. HDU 6184 Counting Stars 经典三元环计数

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6184 题意: n个点m条边的无向图,问有多少个A-structure 其中A-structure满足V ...

  2. [hdu 6184 Counting Stars(三元环计数)

    hdu 6184 Counting Stars(三元环计数) 题意: 给一张n个点m条边的无向图,问有多少个\(A-structure\) 其中\(A-structure\)满足\(V=(A,B,C, ...

  3. hdu6184 Counting Stars 【三元环计数】

    题目链接 hdu6184 题解 题意是让我们找出所有的这样的图形: 我们只需要求出每条边分别在多少个三元环中,记为\(x\),再然后以该点为中心的图形数就是\({x \choose 2}\) 所以我们 ...

  4. Codeforces Gym 100342J Problem J. Triatrip 求三元环的数量 bitset

    Problem J. Triatrip Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100342/at ...

  5. Codeforces Gym 100342J Problem J. Triatrip 三元环

    题目链接: http://codeforces.com/gym/100342 题意: 求三元环的个数 题解: 用bitset分别统计每个点的出度的边和入度的边. 枚举每一条边(a,b),计算以b为出度 ...

  6. Codeforces Gym 100342J Problem J. Triatrip bitset 求三元环的数量

    Problem J. TriatripTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100342/att ...

  7. BZOJ 3498 PA2009 Cakes(三元环处理)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3498 [题目大意] N个点m条边,每个点有一个点权a. 对于任意一个三元环(j,j,k ...

  8. BZOJ3498PA2009 Cakes——三元环

    题目描述 N个点m条边,每个点有一个点权a.对于任意一个三元环(j,j,k)(i<j<k),它的贡献为max(ai,aj,ak) 求所有三元环的贡献和.N<100000,,m< ...

  9. Codechef SUMCUBE Sum of Cubes 组合、三元环计数

    传送门 好久没有做过图论题了-- 考虑\(k\)次方的组合意义,实际上,要求的所有方案中导出子图边数的\(k\)次方,等价于有顺序地选出其中\(k\)条边,计算它们在哪一些图中出现过,将所有方案计算出 ...

随机推荐

  1. 利用js代码屏蔽f12,右键,粘贴,复制,剪切,选中,操作!!秀!秀!秀!

    koala 专注于个人技术分享 屏蔽f12审查 <script> document.onkeydown = function () { if (window.event && ...

  2. HTML DOM focus() 方法

    目录 HTML DOM focus() 方法 实例 定义和使用 浏览器支持 语法 参数 技术描述 更多实例 实例 实例 HTML DOM focus() 方法 实例 为 <a> 元素设置焦 ...

  3. poj 1064 求解最大化问题

    对于二分而言,如果判断条件比较简单的话,在求解最大化或者最小化问题的时候就比较适用但是这道题目吖的卡精度.. #include<cstdio> #include<iostream&g ...

  4. charles 抓包 (二)

    本文基于charles 抓包 https (1)中的配置完成. 1.移动设备上的网络请求 打开要调试的APP,请求就会先发送到Charles,然后验证是否允许访问. 当点击允许后,可以在Proxy - ...

  5. Java枚举相关知识

    JAVA枚举 很多编程语言都提供了枚举的概念,但是java直到1.5之后才提出了枚举的概念,出现比这个语言本身晚10年. 主要作用是用于定义有限个数对象的一种结构(多例设计),枚举就属于多例设计并且其 ...

  6. 【ES6 】const命令

    本质 const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动. 对于简单类型的数据(数值.字符串.布尔值),值就保存在变量指向的那个内存地址,因此等同于常量. ...

  7. 【ExtJs】在Ext.grid.Panel中,两列的值相乘作为第三列的值的实现

    如: 商品总价=商品单价*商品数量 方法: 商品总价列,使用其renderer属性,为期定义一个方法,该方法将当前record中的另外两列中2个数据相乘后渲染到该商品总价列.

  8. 【异常】The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.

    1 详细异常信息 The last packet sent successfully to the server was milliseconds ago. The driver has not re ...

  9. Linux中/etc/inittab文件

    1. inittab基本概念 a) init进程: Linux在完成核内引导(内核镜像已被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,接着通过启动一个用户级程序init来启动其 ...

  10. shell脚本基础和grep文本处理工具企业应用1

      bash特性及bash脚本编程初步: 用户要跟计算机交互就需要有终端,比如:显示器.键鼠等,在终端有附着的接口程序 GUI:KDE.GNome.Xfce CLI:/etc/shells bash ...