HDU 4635 Strongly connected (有向图的强连通分量)
2016-06-20 21:04
489 查看
Strongly connected
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)[align=left]Problem Description[/align]
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.
[align=left]Input[/align]
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.
[align=left]Output[/align]
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.
[align=left]Sample Input[/align]
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
[align=left]Sample Output[/align]
Case 1: -1
Case 2: 1
Case 3: 15
题解
问:最多加多少条边,使得原图不是强连通图
可以反向思考,假设原图已满边,即sum=n*(n-1),减去多少条边使其不是强连通图
直接加边sss=n*(n-1)-m;
用Tarjan求出强连通分量并缩点,将缩好的点分为两部分,一部分到另一部分没有边(即这个点的入度或出度为0),然后用sss减去这两部分能构成的变数。
假设第i个强连通分量有num[i]个点,则它与另一半的图所能连接的边数为num[i]*(n-num[i]),求这个的最小值,减去就行了。
代码
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; const int MAXN = 100000+100; /* * Tarjan算法 * 复杂度O(N+M) */ struct Edge{ int to,next; }edge[MAXN]; int head[MAXN],tot; int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~scc int Index,top; int scc;//强连通分量的个数 bool Instack[MAXN]; int num[MAXN];//各个强连通分量包含点的个数,数组编号1~scc void init() { tot=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v) { edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } void Tarjan(int u) { int v; Low[u]=DFN[u]=++Index; Stack[top++]=u; Instack[u]=true; for(int i=head[u];i!=-1;i=edge[i].next){ v=edge[i].to; if(!DFN[v]){ Tarjan(v); if(Low[u]>Low[v]) Low[u]=Low[v]; } else if(Instack[v]&&Low[u]>DFN[v]) Low[u]=DFN[v]; } if(Low[u]==DFN[u]){ scc++; do{ v=Stack[--top]; Instack[v]=false; Belong[v]=scc; num[scc]++; } while(v!=u); } } void solve(int n) { memset(DFN,0,sizeof(DFN)); memset(Instack,false,sizeof(Instack)); memset(num,0,sizeof(num)); Index=top=scc=0; for(int i=1;i<=n;i++) if(!DFN[i]) Tarjan(i); } int in[MAXN],out[MAXN]; int main() { int T; int iCase=0; scanf("%d",&T); while(T--){ iCase++; init(); int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); addedge(u,v); } solve(n); if(scc==1){ printf("Case %d: -1\n",iCase); continue; } for(int i=1;i<=scc;i++){ in[i]=0; out[i]=0; } for(int u=1;u<=n;u++){ for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(Belong[u]==Belong[v]) continue; out[Belong[u]]++; in[Belong[v]]++; } } long long sss=(long long)n*(n-1)-m; long long ans=0; for(int i=1;i<=scc;i++){ if(in[i]==0||out[i]==0) ans=max(ans,sss-(long long)num[i]*(n-num[i])); } printf("Case %d: %lld\n",iCase,ans); } }
相关文章推荐
- windows 上安装2个mysql 无法启动错误处理
- CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
- CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
- CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
- CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
- CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
- CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
- CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
- CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
- CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
- CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
- CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
- CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
- CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
- CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
- 20145101《JAVA程序设计》课程总结
- mysql5.7 二进制包安装
- 【HDOJ】【百度之星】5699 货物运输
- 第十六周上机实践项目5(2):小玩文件
- Git - 使用指南