传送门

题目描述
你是活跃在历史幕后的一名特工,为了世界和平而夜以继日地努力着。
这个世界有N个国家,编号为1..N;
你的目的是在这N个国家之间建立尽可能多的友好关系。
你为了制定一个特工工作的计划,作出了一张当今国际关系的示意图。
你准备了一张非常大的画纸,先画下了代表每个国家的N个点。
接下来,为了表示现在的国际关系,画下了M个连接两个国家的有向边;
其中从国家u连向国家v的有向边,表示国家u向国家v派遣了大使,下文称作边(u,v)。
这样就做出了N个点M条边的当今国际关系示意图。 作为两国友好关系的开端,两国之间需要进行「友好条约缔结会议」,以下简称会议。
如果某两个国家p和q要进行会议,那么需要一个向两国都派遣了大使的国家x作为中介。
会议结束后,会议的双方相互向对方的国家派遣大使。
换句话说,为了让国家p和国家q进行会议,必须存在一个国家x满足边(x,p)和边(x,q)都存在;
并且在会议后添加两条边(p,q)和(q,p)(如果需要添加的某条边已经存在则不添加)。
你的工作是对于可以进行会议的两国,选择会议的中介并促使会议进行。
使用这张图进行工作的模拟的话,世界距离和平还有多远的一个重要的基准就是这张图上的边数。 现在给出国家的个数以及当今国际关系的情报,请你求出反复选择两个国家,促使它们进行会议后,图上最多会有多少条边。 输入
第一行两个空格分隔的整数N和M,分别表示世界上国家的个数和图中的边数。
接下来M行描述画纸上的有向边的信息,其中第i行有两个空格分隔的整数ai和bi,表示图中有一条从ai到bi的有向边。 输出
输出一行一个整数,表示能实现的边数的最大值。
注意这个边数包括原有的边数和新连接的边数。

题目描述

样例输入

样例输出

样例解释
国家1作为中介国,国家2与3开会。
国家4作为中介国,国家3与5开会。
国家3作为中介国,国家2与5开会。

样例输入输出

数据范围:1≤N≤105,1≤M≤2×105,1≤ai,bi≤N,ai≠bi,(ai,bi)≠(aj,bj)

参考资料:

  [1]:http://icpc.upc.edu.cn/blog/?p=108

题意(摘抄自[1]):

  如果存在有向边<a,b>和<a,c>,就添加两条有向边<b,c>和<c,b>(已经存在就不添加),问最多有多少条边;

题解:

  昨天比赛做这道题的时候,想到了SCC,但我真的用SCC了,中间过程处理的不好(代码写搓了,逃)........

  今天晚上补这道题,看了看题解,和昨天自己想的差不多,就是代码实现上,[1]并没有用SCC知识用SCC思考这道题的做法;

  哎,欠缺的还是太多了,理解了将近半个小时,终于理解了,tql;

  下面谈谈我的进一步理解:

  (看会专业课先,理解明天写,下周要考两门,orz)

  对于某节点 u,如果 u 有 > 1 个儿子 v1,v,.......,vx,那么 v1,v,.......,vx  及其所有儿子可构成强连通;

  例如:

  

  节点①有两个儿子②③,那么②及其所有儿子④⑥,③及其所有儿子⑤构成强连通;

  即②③④⑤⑥构成强连通;

  同属于同一个强连通的所有节点的信息可以集中到一个节点上,假设这5个节点的信息集中到节点②上;

 int fa[maxn];///fa[i]:i所处的强连通的代表节点
ll tot[maxn];///tot[i]:i所处的强连通的个数,只有代表节点的tot[i]才有意义

  fa初始化为-1,tot初始化为1;

  对于上图,合并后的信息为:

  fa[2]=-1,fa[3,4,5,6]=2;

  tot[2]=5;(只有②节点的tot有用)

  那么,最重要的就是合并操作,具体如下:

 int Find(int x)///查找x所处的强连通的代表节点
{
return fa[x] == - ? x:fa[x]=Find(fa[x]);
}
void DFS(int u,int x)
{
for(int i=head[u];~i;i=G[i].next)
{
int y=G[i].to; y=Find(y);
if(x == y)
continue; fa[y]=x;
tot[x] += tot[y];
DFS(y,x);
}
} ///合并
bool update=true;
while(update)
{
update=false;
for(int u=;u <= n;++u)
{
///判断u是否已经处于某个强连通中
///如果u处于某个强连通中,x=u,反之x=-1
int x=tot[Find(u)] == ? -:u;
for(int i=head[u];~i;i=G[i].next)
{
/**
如果u不处于某个强连通中:
①如果其包含>1个儿子节点,其儿子节点可以构成强连通
如果u本身就处于某个强连通中:
①其所有儿子全部在这个强连通中
*/
int y=G[i].to;
if(x == -)
x=y;
else///将强连通中的节点信息合并到Find(x)中
{
x=Find(x);
y=Find(y); if(x == y)///在同一个强连通中
continue; update=true;
fa[y]=x;
tot[x] += tot[y];
DFS(y,x);///将y的所有儿子节点合并到Find(x)中
}
}
}
}

AC代码(偷偷换成了我的风格):

 #include<bits/stdc++.h>
using namespace std;
#define ll long long
#define memF(a,b,n) for(int i=0;i <= n;a[i]=b,++i);
const int maxn=1e5+; int n,m;
int num;
int head[maxn];
struct Edge
{
int to;
int next;
}G[maxn<<];
void addEdge(int u,int v)
{
G[num]={v,head[u]};
head[u]=num++;
}
int fa[maxn];///fa[i]:i所处的强连通的代表节点
ll tot[maxn];///tot[i]:i所处的强连通的个数,只有代表节点的tot[i]才有意义
int Find(int x)///查找x所处的强连通的代表节点
{
return fa[x] == - ? x:fa[x]=Find(fa[x]);
}
void DFS(int u,int x)
{
for(int i=head[u];~i;i=G[i].next)
{
int y=G[i].to; y=Find(y);
if(x == y)
continue; fa[y]=x;
tot[x] += tot[y];
DFS(y,x);
}
}
ll Solve()
{
memF(fa,-,n);
memF(tot,,n);
bool update=true;
while(update)
{
update=false;
for(int u=;u <= n;++u)
{
///判断u是否已经处于某个强连通中
///如果u处于某个强连通中,x=u,反之x=-1
int x=tot[Find(u)] == ? -:u;
for(int i=head[u];~i;i=G[i].next)
{
/**
如果u不处于某个强连通中:
①如果其包含>1个儿子节点,其儿子节点可以构成强连通
如果u本身就处于某个强连通中:
①其所有儿子全部在这个强连通中
*/
int y=G[i].to;
if(x == -)
x=y;
else///将强连通中的节点信息合并到Find(x)中
{
x=Find(x);
y=Find(y); if(x == y)///在同一个强连通中
continue; update=true;
fa[y]=x;
tot[x] += tot[y];
DFS(y,x);///将y的所有儿子节点合并到Find(x)中
}
}
}
} ll ans=;
for(int u=;u <= n;++u)
{
if(fa[u] == -)
ans += tot[u]*(tot[u]-);
for(int i=head[u];~i;i=G[i].next)
{
int x=Find(u);
int y=Find(G[i].to);
if(x != y)
ans++;
}
} return ans;
}
void Init()
{
num=;
memF(head,-,n);
}
int main()
{
scanf("%d%d",&n,&m);
Init();
for(int i=;i <= m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
addEdge(u,v);
}
printf("%lld\n",Solve()); return ;
}

JOISC2014 Day2 E "交朋友" (思维+假的SCC)的更多相关文章

  1. LOJ #2877. 「JOISC 2014 Day2」交朋友 并查集+BFS

    这种图论问题都挺考验小思维的. 首先,我们把从 $x$ 连出去两条边的都合并了. 然后再去合并从 $x$ 连出去一条原有边与一条新边的情况. 第一种情况直接枚举就行,第二种情况来一个多源 bfs 即可 ...

  2. POJ 1904 King's Quest(SCC的巧妙应用,思维题!!!,经典题)

    King's Quest Time Limit: 15000MS   Memory Limit: 65536K Total Submissions: 10305   Accepted: 3798 Ca ...

  3. zoj 4124 "Median" (思维?假的图论?)

    传送门 来源:2019 年“浪潮杯”第十届山东省 ACM 省赛 题意: 对于一个包含n个数的(n为奇数)序列val[ ],排序后的 val[ (n+1) / 2 ] 定义为 median: 有 n 个 ...

  4. 图论+思维(2019牛客国庆集训派对day2)

    题意:https://ac.nowcoder.com/acm/contest/1107/J n个点的完全图编号0-n-1,第i个点的权值为2^i,原先是先手选取一些边,然后后手选取一些点,满足先手选取 ...

  5. <每日一题> Day2:CodeForces-1141C.PolycarpRestoresPermutation(思维题)

    原题链接 参考代码: #include <iostream> #include <cstring> using namespace std; + , INF = 0x3f3f3 ...

  6. Spark机器学习 Day2 快速理解机器学习

    Spark机器学习 Day2 快速理解机器学习 有两个问题: 机器学习到底是什么. 大数据机器学习到底是什么. 机器学习到底是什么 人正常思维的过程是根据历史经验得出一定的规律,然后在当前情况下根据这 ...

  7. vue源码逐行注释分析+40多m的vue源码程序流程图思维导图 (diff部分待后续更新)

    vue源码业余时间差不多看了一年,以前在网上找帖子,发现很多帖子很零散,都是一部分一部分说,断章的很多,所以自己下定决定一行行看,经过自己坚持与努力,现在基本看完了,差ddf那部分,因为考虑到自己要换 ...

  8. 【NOIP 2017】Day2 T3 列队

    Problem Description \(Sylvia\) 是一个热爱学习的女孩子. 前段时间,\(Sylvia\) 参加了学校的军训.众所周知,军训的时候需要站方阵. \(Sylvia\) 所在的 ...

  9. 思维题练习专场-DP篇(附题表)

    转载请注明原文地址http://www.cnblogs.com/LadyLex/p/8536399.html 听说今年省选很可怕?刷题刷题刷题 省选已经结束了但是我们要继续刷题刷题刷题 目标是“有思维 ...

随机推荐

  1. Mysql常用的三种数据库引擎比较

    ISAM:ISAM是一个定义明确且历经时间考验的数据表格管理方法,它在设计之时就考虑到数据库被查询的次数要远大于更新的次数.因此,ISAM执行读取操作的速度很快,而且不占用大量的内存和存储资源.ISA ...

  2. redis是当前流行的nosql数据库

    redis是当前流行的nosql数据库,很多网站都用它来做缓存,今天我们来安装并配置下redis 二.安装并配置redis 1.安装redis sudo apt-get install redis-s ...

  3. laravel学习文档

    https://github.com/barryvdh/laravel-debugbar Laravel 精选资源大全 http://laravelacademy.org/post/153.html ...

  4. day39-Spring 15-Spring的JDBC模板:C3P0连接池配置

    <!-- 配置C3P0连接池 --> <bean id="dataSource2" class="com.mchange.v2.c3p0.ComboPo ...

  5. SDUT-3364_欧拉回路

    数据结构实验之图论八:欧拉回路 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 在哥尼斯堡的一个公园里,有七座桥将普雷格 ...

  6. Ubuntu 16.04下OLSR协议安装教程

    OLSR是根据MANET的要求,在传统的LS(Link state)协议的基础上优化的. OLSR中的关键概念是多点转播(MPRs),MPRs是在广播洪泛的过程中挑选的转发广播的节点.传统的链路状态协 ...

  7. js cookies 的写入、读取、删除

    //写cookies //escape() 函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串.function setCookie(name,value) {     var Days ...

  8. shell学习(21)- tr

    Linux tr 命令用于转换或删除文件中的字符. tr 指令从标准输入设备读取数据,经过字符串转译后,将结果输出到标准输出设备. 在tr中利用集合的概念,可以轻松地将字符从一个集合映射到另一个集合中 ...

  9. 三、python-json、正则

    一.json   1.导入模块 import json 2.常用方法 dumps:序列化,把一个Python对象转化成json字符串 loads:反序列化,把json字符串转化成python dump ...

  10. hdu2149 巴什博奕

    n表示先手胜 p表示先手负 1~N N+1 N+2~2*N+1 2*N+2 2*N+3~3*N+2 ... n p n p n ... m总归个数 每次取1~N个根据前面的规律得到,如果m/N==m% ...