题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4635

先判断图是否强连通。如果不是强连通的,那么缩点。

我们的目的是加最多的边,那么最后的图中,肯定两个集合,这两个集合都是强联通的,

一个集合到一个集合只有单向边。我们先让图是满图,然后通过删边来求的:有n*(n-1)条边,然后删掉已有的边m

,然后还有删掉两个集合的边n1*(n-n1),n1为其中一个集合的顶点个数,因为这里是单向边。

那么答案就是ans=n*(n-1)-m-n1*(n-n1),

我们要使ans最大,那么n1*(n-n1)就要越小

 最终添加完边的图,肯定可以分成两个部 X 和 Y ,其中只有X到Y的边没有Y到X的边,那么要使得边数尽可能的多,则X部肯定是一个完全图,Y部也是,同时X部中每个点到Y部的每个点都有一条边,假设X部有x个点,Y部有y个点,有x+y=n,同时边数F=x*y+x*(x-1)+y*(y-1),整理得:F=N*N-N-x*y,(然后去掉已经有了的边m,就是答案),当x+y为定值时,二者越接近,x*y越大,所以要使得边数最多,那么X部和Y部的点数的个数差距就要越大,所以首先对于给定的有向图缩点,对于缩点后的每个点,如果它的出度或者入度为0,那么它才有可能成为X部或者Y部,所以只要求缩点之后的出度或者入度为0的点中,包含节点数最少的那个点,令它为一个部,其它所有点加起来做另一个部,就可以得到最多边数的图了

#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
#define N 100005
#define INF 0xfffffff
using namespace std; int head[N], cnt;
int top, Is[N], Stack[N], low[N], dfn[N], Time, n, m;
int nBlock, Block[N];
int Cnt[N], Out[N], In[N];
struct Edge
{
int v, next;
}e[N];
void Init()
{
Time = cnt = top = nBlock = ;
memset(Cnt, , sizeof(Cnt));
memset(low, , sizeof(low));
memset(dfn, , sizeof(dfn));
memset(Stack, , sizeof(Stack));
memset(Is, , sizeof(Is));
memset(Out, , sizeof(Out));
memset(In, , sizeof(In));
memset(Block, , sizeof(Block));
memset(head, -, sizeof(head));
}
void Add(int u, int v)
{
e[cnt].v = v;
e[cnt].next = head[u];
head[u] = cnt++;
}
void Tajar(int u, int father)
{
Stack[top++]=u;
low[u] = dfn[u] = ++Time;
Is[u] = ;
int v;
for(int i=head[u]; i!=-; i=e[i].next)
{
v = e[i].v;
if(!dfn[v])
{
Tajar(v, u);
low[u] = min(low[u], low[v]);
}
else if(Is[v])
low[u] = min(low[u], dfn[v]);
}
if(low[u]==dfn[u])
{
++nBlock;
do
{
v=Stack[--top];
Is[v] = ;
Block[v] = nBlock;
Cnt[nBlock]++;
}while(u!=v);
}
} int main()
{
int T, t=, x, y;
scanf("%d", &T);
while(T--)
{
Init();
scanf("%d%d", &n, &m);
for(int i=; i<=m; i++)
{
scanf("%d%d", &x, &y);
Add(x, y);
}
for(int i=; i<=n; i++)
{
if(!low[i])
Tajar(i, -);
}
for(int i=; i<=n; i++)
{
for(int j=head[i]; j!=-; j=e[j].next)
{
int u = Block[i];
int v = Block[e[j].v];
if(u != v)
{
Out[v]++;
In[u]++;
}
}
}
y = INF;
for(int i=; i<=nBlock; i++)
{
if(!In[i] || !Out[i])
y=min(y, Cnt[i]);
}
x = n - y;
long long ans=(long long)n*(n-)-x*y-m;
if(nBlock==)
printf("Case %d: -1\n", t++);
else
printf("Case %d: %lld\n", t++, ans);
}
return ;
}

一年之后又来写

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<string>
#include<stack>
#include<vector>
#include<map>
using namespace std;
#define N 100305
#define INF 0x3f3f3f3f
#define met(a, b) memset(a, b, sizeof(a))
typedef long long LL; vector<vector<int> >G;
stack<int>sta;
int low[N], dfn[N], block[N], Block, vis[N];
int In_degree[N], Out_degree[N], Time, n, cnt[N]; void Init()
{
met(low, );
met(dfn, );
met(block, );
met(vis, );
met(In_degree, );
met(Out_degree, );
met(cnt, );
G.clear();
G.resize(n+);
while(sta.size())sta.pop();
Time = Block = ;
} void Tarjan(int u)
{
low[u] = dfn[u] = ++Time;
sta.push(u);
vis[u] = ;
int len = G[u].size(), v;
for(int i=; i<len;i++)
{
v = G[u][i];
if(!dfn[v])
{
Tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(vis[v])
{
low[u] = min(low[u], dfn[v]);
}
}
if(low[u] == dfn[u])
{
Block++;
do{
v = sta.top();
sta.pop();
block[v] = Block;
cnt[Block]++;
vis[v] = ;
}while(u!=v);
}
} int main()
{
int T, m, t = , u, v;
scanf("%d", &T);
while(T--)
{
scanf("%d %d", &n, &m);
Init();
for(int i=; i<=m; i++)
{
scanf("%d %d", &u, &v);
G[u].push_back(v);
}
for(int i=; i<=n; i++)
{
if(!dfn[i])
Tarjan(i);
}
if(Block == )
{
printf("Case %d: -1\n", t++);
continue;
}
for(int i=; i<=n; i++)
{
int len = G[i].size();
for(int j=; j<len; j++)
{
u = block[i];
v = block[G[i][j]];
if(u != v)
{
In_degree[v]++;
Out_degree[u]++;
}
}
}
int ans = , sum = n*(n-) - m; for(int i=; i<=Block; i++)
{
if(!In_degree[i] || !Out_degree[i])
ans = max(ans, sum - cnt[i]*(n-cnt[i]));
}
printf("Case %d: %d\n", t++, ans);
}
return ;
}

Strongly connected---hdu4635(强联通分量)的更多相关文章

  1. Strongly connected(hdu4635(强连通分量))

    /* http://acm.hdu.edu.cn/showproblem.php?pid=4635 Strongly connected Time Limit: 2000/1000 MS (Java/ ...

  2. 强联通分量(tarjan算法+算法简介)

    题目描述 ›对于一个有向图顶点的子集S,如果在S内任取两个顶点u和v,都能找到一条从u到v的路径,那么就称S是强连通的.如果在强连通的顶点集合S中加入其他任意顶点集合后,它都不再是强连通的,那么就称S ...

  3. Kosaraju算法---强联通分量

    1.基础知识 所需结构:原图.反向图(若在原图中存在vi到vj有向边,在反向图中就变为vj到vi的有向边).标记数组(标记是否遍历过).一个栈(或记录顶点离开时间的数组).      算法描叙: :对 ...

  4. [CF #236 (Div. 2) E] Strictly Positive Matrix(强联通分量)

    题目:http://codeforces.com/contest/402/problem/E 题意:给你一个矩阵a,判断是否存在k,使得a^k这个矩阵全部元素都大于0 分析:把矩阵当作01矩阵,超过1 ...

  5. UVa 11324 & 强联通分量+DP

    题意: 一张无向图,求点集使其中任意两点可到达. SOL: 强联通分量中的点要么不选要么全都选,然后缩点DAG+DP 记录一下思路,不想写了...代码满天飞.

  6. BZOJ 1051 & 强联通分量

    题意: 怎么说呢...这种题目有点概括不来....还是到原题面上看好了... SOL: 求出强联通分量然后根据分量重构图,如果只有一个点没有出边那么就输出这个点中点的数目. 对就是这样. 哦还有论边双 ...

  7. 洛谷 P2661 信息传递 Label:并查集||强联通分量

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  8. POJ 2186-Popular Cows (图论-强联通分量Korasaju算法)

    题目链接:http://poj.org/problem?id=2186 题目大意:有n头牛和m对关系, 每一对关系有两个数(a, b)代表a牛认为b牛是“受欢迎”的,且这种关系具有传递性, 如果a牛认 ...

  9. POJ 1904 King's Quest 强联通分量+输入输出外挂

    题意:国王有n个儿子,现在这n个儿子要在n个女孩里选择自己喜欢的,有的儿子可能喜欢多个,最后国王的向导给出他一个匹配.匹配有n个数,代表某个儿子和哪个女孩可以结婚.已知这些条件,要你找出每个儿子可以和 ...

随机推荐

  1. 关于VS2012连接MySql数据库时无法选择数据源

    您的C#开发工具是用VS2012吗?    No! return;    您的数据库用的是MySql吗?     No! return;    您新建ADO.NET数据实体模型的时候选择数据源的时候没 ...

  2. 做asp.net的在别人眼中都是渣渣吗?

    做asp.net的在别人眼中都是渣渣吗?

  3. 建造者模式(build pattern)-------创造型模式

    将一个复杂对象的构建与它的标示分离,使得同样的构建过程可以创建不同的标示. 建造者模式是较为复杂的创建型模式,它将客户端与包含多个组成部分(或部件)的复杂对象的创建过程分离,客户端无须知道复杂对象的内 ...

  4. .Net中的序列化和反序列化详解

    序列化通俗地讲就是将一个对象转换成一个字节流的过程,这样就可以轻松保存在磁盘文件或数据库中.反序列化是序列化的逆过程,就是将一个字节流转换回原来的对象的过程. 然而为什么需要序列化和反序列化这样的机制 ...

  5. java (java.exe) 解释器 -D 选项

    java.exe -h 其中: -D<名称>=<值>  : 设置系统属性 如帮助说明的那样,该选项用于设置  java 运行时的 System.getProperty(prop ...

  6. Asp.net 程序优化js,css合并与压缩

    访问时将js和css压缩并且缓存在客户端,采用的是Yahoo.Yui.Compressor组件还完成的,从这里可下载 创建一个IHttpHandler来处理文件 ) }; )              ...

  7. 移动端meta 解释

    移动端meta 解释 <meta name="viewport" content="width=device-width, initial-scale=1.0, u ...

  8. swift学习笔记之控制流

    控制流: 1.if语句 let count = { print("yes") }else{ print("no") } 2.switch语句 (1)Swift中 ...

  9. Linux mii-tool 命令

    mii-tool 用来查看或设置网卡的相关参数,该命令已经过时了,推荐使用 ethtool 命令 [root@localhost ~]$ mii-tool -v eth1 # 查看网卡的相关信息,包括 ...

  10. 查询软件和硬件列表清单[将文章里代码另存为 list.vbs,双击运行就会出现一个html页面]

    '==========================================================================' Name: 查询软件和硬件列表清单' 不支持W ...