传送门

题目描述
你是活跃在历史幕后的一名特工,为了世界和平而夜以继日地努力着。
这个世界有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. day4new-转自金角大王

    Python之路,Day4 - Python基础4 (new版)   本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 ...

  2. Spring中使用DataSourceTransactionManager进行事务管理的xml配置

    在一个业务的实现过程中,可能需要多条sql完成对数据库的操作,比如账户登录,需要匹配用户名和密码,然后要增加积分,还要记录登录的ip和时间,这可能需要三个sql语句,这三个语句应当是一个整体,任意一个 ...

  3. 【水滴石穿】AB-B-Clone

    地址: 源码 运行效果 无别的效果,代码如下 //index.js /** * @format * @lint-ignore-every XPLATJSCOPYRIGHT1 */ import {Ap ...

  4. Inno setup 卸载时删除程序文件夹(文件)

    Inno setup 卸载时删除程序文件夹(文件) //删除所有配置文件以达到干净卸载的目的 procedure CurUninstallStepChanged(CurUninstallStep: T ...

  5. JavaScript学习之 倒计时

    倒计时很常见,例如离XX活动还有XX天XX小时XX分XX秒,然后逐秒减少,实现很简单,我只是想记录这过程中的一点小坑. 先上代码: <html> <head> <meta ...

  6. 写一个nginx监控日志

    下面的代码是实现一个nginx监控日志功能,是不是很好玩呢.

  7. Java练习 SDUT-2787_加密术

    加密术 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 加密技术是一种常用的安全保密手段,利用加密技术可以把重要的数据变 ...

  8. 2018-7-9-dotnet-设计规范-·-数组定义

    title author date CreateTime categories dotnet 设计规范 · 数组定义 lindexi 2018-07-09 14:26:48 +0800 2018-2- ...

  9. oralce函数 STDDEV([distinct|all]x)

    [功能]统计数据表选中行x列的标准误差. [参数]all表示对所有的值求标准误差,distinct只对不同的值求标准误差,默认为all 如果有参数distinct或all,需有空格与x(列)隔开. [ ...

  10. 04使用harbor配置私仓

    安装harbor之前,需要安装好Python,Docker,DockerCompose.Python需要2.7以上的版本,Docker需要1.10以上的版本:Docker Compose 需要1.6. ...