HDU4625:Strongly connected(思维+强连通分量)
Strongly connected
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4765 Accepted Submission(s): 1880
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4635
Description:
Give a simple directed graph with N nodes and M edges. Please tell me the maximum number of the edges you can add that the graph is still a simple directed graph. Also, after you add these edges, this graph must NOT be strongly connected.
A simple directed graph is a directed graph having no multiple edges or graph loops.
A strongly connected digraph is a directed graph in which it is possible to reach any node starting from any other node by traversing edges in the direction(s) in which they point.
Input:
The first line of date is an integer T, which is the number of the text cases.
Then T cases follow, each case starts of two numbers N and M, 1<=N<=100000, 1<=M<=100000, representing the number of nodes and the number of edges, then M lines follow. Each line contains two integers x and y, means that there is a edge from x to y.
Output:
For each case, you should output the maximum number of the edges you can add.
If the original graph is strongly connected, just output -1.
Sample Input:
3
3 3
1 2
2 3
3 1
3 3
1 2
2 3
1 3
6 6
1 2
2 3
3 1
4 5
5 6
6 4
Sample Output:
Case 1: -1
Case 2: 1
Case 3: 15
题意:
给出一个有向图,保证图中无重边。现在要求加尽量多的边,使得最终的图不是强连通的,即任意两点可以互相到达,并且图中无重边。
题解:
可以想到,最终的图是一个二部图,设左边这部分为X,右边这部分为Y,那么X,Y之间只有单向边,同时X,Y中所有点都是强连通的,此时满足条件。
现在的问题就是这么确定这个X,Y。假设X中有x个点,同理,Y中有y个点,然后来计算一波:
此时图中的边数为x*(x-1)+y*(y-1)+x*y=x2+y2+x*y-x-y=(x+y)2-x*y-x-y=n2-n-x*y。现在要使得边数最大,那么x*y就尽量小,又因为x+y为定值,那么要么x尽可能小,要么y尽可能小就是了。
然后由于图中可能存在环,我们就先用Tarjan缩点,然后选取包含点数最少,并且出度或者入度为0的那个点作为X部,之后计算一波就行了。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 1e5+;
int t,n,m,tot;
int head[N],num[N],in[N],out[N];
stack <int> s;
struct Edge{
int u,v,next;
}e[N<<],g[N<<];
void adde(int u,int v){
e[tot].u=u;e[tot].v=v;e[tot].next=head[u];head[u]=tot++;
}
int T,cc;
int scc[N],dfn[N],low[N],vis[N];
void Tarjan(int u){
dfn[u]=low[u]=++T;vis[u]=;
s.push(u);
for(int i=head[u];i!=-;i=e[i].next){
int v=e[i].v;
if(!vis[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}else if(!scc[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
cc++;int now;
do{
now = s.top();s.pop();
scc[now]=cc;
num[cc]++;
}while(!s.empty() && now!=u);
}
}
int main(){
cin>>t;
int Case=;
while(t--){
Case++;
memset(head,-,sizeof(head));tot=;
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
g[i].u=u;g[i].v=v;
adde(u,v);
}
memset(dfn,,sizeof(dfn));
memset(scc,,sizeof(scc));T=;
memset(vis,,sizeof(vis));cc=;
memset(num,,sizeof(num));
memset(in,,sizeof(in));
memset(out,,sizeof(out));
for(int i=;i<=n;i++){
if(!vis[i]) Tarjan(i);
}
printf("Case %d: ",Case);
if(cc==){
puts("-1");
continue ;
}
for(int i=;i<=m;i++){
int u=g[i].u,v=g[i].v;
if(scc[u]==scc[v]) continue ;
in[scc[v]]++;out[scc[u]]++;
}
ll tmp = n*(n-)-m;
ll ans = ;
for(int i=;i<=cc;i++){
if(!in[i] || !out[i]) ans=max(ans,tmp-num[i]*(n-num[i]));
}
cout<<ans<<endl;
}
return ;
}
HDU4625:Strongly connected(思维+强连通分量)的更多相关文章
- [HDOJ4635]Strongly connected(强连通分量,缩点)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4635 题意:给一张图,问最多往这张图上加多少条边,使这张图仍然无法成为一个强连通图. 起初是先分析样例 ...
- HDU 4635 Strongly connected(强连通分量,变形)
题意:给出一个有向图(不一定连通),问最多可添加多少条边而该图仍然没有强连通. 思路: 强连通分量必须先求出,每个强连通分量包含有几个点也需要知道,每个点只会属于1个强连通分量. 在使图不强连通的前提 ...
- HDU 4635 Strongly connected ——(强连通分量)
好久没写tarjan了,写起来有点手生,还好1A了- -. 题意:给定一个有向图,问最多添加多少条边,让它依然不是强连通图. 分析:不妨考虑最大时候的临界状态(即再添加一条边就是强连通图的状态),假设 ...
- HDU 4635 Strongly connected(强连通分量缩点+数学思想)
题意:给出一个图,如果这个图一开始就不是强连通图,求出最多加多少条边使这个图还能保持非强连通图的性质. 思路:不难想到缩点转化为完全图,然后找把它变成非强连通图需要去掉多少条边,但是应该怎么处理呢…… ...
- HDU 4635 —— Strongly connected——————【 强连通、最多加多少边仍不强连通】
Strongly connected Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u ...
- HDU 4635:Strongly connected(强连通)
http://acm.hdu.edu.cn/showproblem.php?pid=4635 题意:给出n个点和m条边,问最多能添加几条边使得图不是一个强连通图.如果一开始强连通就-1.思路:把图分成 ...
- Codeforces 950E Data Center Maintenance ( 思维 && 强连通分量缩点 )
题意 : 给出 n 个点,每个点有一个维护时间 a[i].m 个条件,每个条件有2个点(x,y)且 a[x] != a[y].选择最少的 k (最少一个)个点,使其值加1后,m个条件仍成立. 分析 : ...
- hdu 4635 Strongly connected(强连通)
考强连通缩点,算模板题吧,比赛的时候又想多了,大概是不自信吧,才开始认真搞图论,把题目想复杂了. 题意就是给你任意图,保证是simple directed graph,问最多加多少条边能使图仍然是si ...
- HDU4635 Strongly connected【强连通】
题意: 给一个n个点的简单有向图,问最多能加多少条边使得该图仍然是简单有向图,且不是强连通图.简单有向图的定义为:没有重边,无自环. 强连通图的定义为:整个图缩点后就只有一个点,里面包含n个原点,也就 ...
随机推荐
- leetcode-组合总数IV(动态规划)
377. 组合总和 Ⅳ 给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数. 示例: nums = [1, 2, 3] target = 4 所有可能的组合为: (1, ...
- Python基础 之 set集合 与 字符串格式化
数据类型的回顾与总结 可变与不可变1.可变:列表,字典2.不可变:字符串,数字,元组 访问顺序:1.直接访问:数字2.顺序访问:字符串,列表,元祖3.映射:字典 存放元素个数:容器类型:列表,元祖,字 ...
- Docker 镜像构建的时候,应该小心的坑
不要改文件 如果run了以后,你还需要进入到容器中,修改容器的配置,那么,这个容器是危险的.一旦容器无法启动,就再也改不了配置.那么你就需要删除和重新run这个容器,而配置要再改一遍.一个可用的镜像在 ...
- 使用 Gradle 配置java项目
注意点 除非调试,不要print ,否则任务不会按照依赖的顺序执行,因为我们自己喜欢调试用print,但是会打乱执行顺序. 排除测试文件: sourceSets.main.java { srcDir ...
- CryptoZombies学习笔记——Lesson3
第三课就开始深入讲解solidity编程技巧了. chapter1: 智能合约的不变性. 合约一旦部署到以太坊后,就不可更改了,所以从一方面来说,智能合约代码的安全性是如此重要,因为一旦发现你的代码里 ...
- for和foreach的一点总结
两者都是数组的循环遍历,但是区别还是有点: for循环,如果块内有事件操作,那么i是不会等事件操作时候在依次增加,而是一次性走完,,也就是依靠下标定位,下标已经走完了,而foreah是依次增加,它是依 ...
- Windows网络编程系列教程之四:Select模型
讲一下套接字模式和套接字I/O模型的区别.先说明一下,只针对Winsock,如果你要骨头里挑鸡蛋把UNIX下的套接字概念来往这里套,那就不关我的事. 套接字模式:阻塞套接字和非阻塞套接字.或者叫同步套 ...
- Ubuntu下erlang连接SQL SERVER 2008
erlang连接SQL Server使用ODBC方法,但在网络上还是缺少资料,自己折腾了2天才成功.现在特记录下来,以供大家借鉴. 基本思路是 erlang odbcserver + unixodbc ...
- IntelliJ IDEA Maven引入
- linux 相关的问题
1,查找当前目录下的文件名,并重定向到文件t中 ls > t mac 下快速补全目录名快捷键tab