hdu 4635 Strongly connected (tarjan)
题意:给一个n个顶点m条弧的简单有向图(无环无重边),求最多能够加入多少条弧使得加入后的有向图仍为简单有向图且不是一个强连通图。假设给的简单有向图本来就是强连通图,那么输出-1.
分析:
1.用tarjan算法求出强连通分量的个数,假设个数为1,那么输出-1,结束,否则运行2
2.如果将一些强连通分量合并为有n1个顶点简单全然图1,而将剩下的强连通分量合并为n2个顶点的简单全然图2,跨这两个简单全然图的弧的方向仅仅能是单向的,如果m1为全然图1内部的弧的数量,m2为为全然图2内部的弧的数量。m3为跨这两个简单全然图的弧的数量,那么
ans=n1*(n1-1)-m1+n2*(n2-1)-m2+n1*n2-m3 ----------------------------------------------------1式
n1+n2=n ----------------------------------------------------2式
m1+m2+m3=m ----------------------------------------------------3式
n*n=(n1+n2)(n1+n2)=n1*n1+n2*n2+2*n1*n2 -----------------------------------------------------4式
所以
ans=n*n-m-n-n1*n2=n*n-m-n-n1*(n-n1)
ans要最大,所以n1*(n-n1)要最小。同一时候要跨图1。图2的弧要单向,
所以在跨图1,图2的弧要单向的情况下。n1尽量小。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 100005
#define INF 1<<30
using namespace std; typedef struct ArcNode
{
int adjvex;//该弧所指向的顶点的位置
struct ArcNode * nextarc;//指向下一条弧的指针
} ArcNode; typedef struct VNode
{
int vertex;
//int In_deg,Out_deg;
int belong;
ArcNode * firstarc;
} VNode; VNode V[MAX];
int DFN[MAX],Stack[MAX],low[MAX];
int top,index,bcnt;
bool instack[MAX];
long long n,m;
int Min;
int cnt;
int k;
int edge[MAX][2]; void init()
{
int a,b;
ArcNode * p;
for(int i=1; i<=n; i++)
{
V[i].vertex=i;
//V[i].In_deg=V[i].Out_deg=0;
V[i].firstarc =NULL;
}
for(int i=0; i<m; i++)
{
scanf("%d%d",&a,&b);
// V[a].Out_deg++;
// V[b].In_deg++;
edge[i][0]=a;
edge[i][1]=b;
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex =b;
p->nextarc =V[a].firstarc ;
V[a].firstarc =p;
}
} void DFS_tarjan(int i)
{
int j;
ArcNode * p;
DFN[i]=low[i]=++index;
Stack[++top]=i;
instack[i]=true;
p=V[i].firstarc ;
while(p!=NULL)
{
j=p->adjvex;
if(!DFN[j])
{
DFS_tarjan(j);
if(low[j]<low[i])//Low(u)为u的子树可以追溯到的最早的栈中节点的次序号
low[i]=low[j];
}
else if(instack[j]&&DFN[j]<low[i])//Low(u)为u可以追溯到的最早的栈中节点的次序号
low[i]=DFN[j];
p=p->nextarc;//
}
if(DFN[i]==low[i])
{
bcnt++;
cnt=0;
int INDEG=0;
int OUTDEG=0;
do
{
j=Stack[top--];//出栈,j是为该强连通分量中一个顶点
instack[j]=false;
//INDEG+=V[j].In_deg;
//OUTDEG+=V[j].Out_deg;
V[j].belong=bcnt;
cnt++;
}
while(i!=j);
for(int kkk=0;kkk<m;kkk++)
{
if(V[edge[kkk][0]].belong==bcnt&&V[edge[kkk][1]].belong!=bcnt)
{
OUTDEG++;
}
if(V[edge[kkk][0]].belong!=bcnt&&V[edge[kkk][1]].belong==bcnt)
INDEG++;
}
if(Min>cnt&&(INDEG==0||OUTDEG==0))
{
Min=cnt;
}
}
} void FREE()
{
ArcNode * p;
ArcNode * q;
for(int i=1; i<=n; i++)
{
p=V[i].firstarc;
while(p!=NULL)
{
q=p;
p=p->nextarc;
free(q);
}
}
} void solve()
{
int i;
top=index=bcnt=0;
memset(DFN,0,sizeof(DFN));
memset(instack,false,sizeof(instack));
for(i=1; i<=n; i++)
{
if(!DFN[i])
DFS_tarjan(i);
}
//printf("%d\n",bcnt);
FREE();
if(bcnt==1)
{
printf("Case %d: -1\n",k);
return;
}
long long ans=n*n-n-m-(Min*(n-Min));
//printf("%d\n",Min);
printf("Case %d: %lld\n",k,ans);
} int main()
{
int t;
scanf("%d",&t);
for(k=1; k<=t; k++)
{
scanf("%lld%lld",&n,&m);
Min=INF;
init();
solve();
}
return 0;
}
hdu 4635 Strongly connected (tarjan)的更多相关文章
- HDU 4635 Strongly connected (Tarjan+一点数学分析)
Strongly connected Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) ...
- HDU 4635 - Strongly connected(2013MUTC4-1004)(强连通分量)
t这道题在我们队属于我的范畴,最终因为最后一个环节想错了,也没搞出来 题解是这么说的: 最终添加完边的图,肯定可以分成两个部X和Y,其中只有X到Y的边没有Y到X的边,那么要使得边数尽可能的多,则X部肯 ...
- hdu 4635 Strongly connected(强连通)
考强连通缩点,算模板题吧,比赛的时候又想多了,大概是不自信吧,才开始认真搞图论,把题目想复杂了. 题意就是给你任意图,保证是simple directed graph,问最多加多少条边能使图仍然是si ...
- HDU 4635 Strongly connected (2013多校4 1004 有向图的强连通分量)
Strongly connected Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- HDU 4635 Strongly connected ——(强连通分量)
好久没写tarjan了,写起来有点手生,还好1A了- -. 题意:给定一个有向图,问最多添加多少条边,让它依然不是强连通图. 分析:不妨考虑最大时候的临界状态(即再添加一条边就是强连通图的状态),假设 ...
- HDU 4635 Strongly connected(强连通分量,变形)
题意:给出一个有向图(不一定连通),问最多可添加多少条边而该图仍然没有强连通. 思路: 强连通分量必须先求出,每个强连通分量包含有几个点也需要知道,每个点只会属于1个强连通分量. 在使图不强连通的前提 ...
- HDU 4635 Strongly connected(强连通分量缩点+数学思想)
题意:给出一个图,如果这个图一开始就不是强连通图,求出最多加多少条边使这个图还能保持非强连通图的性质. 思路:不难想到缩点转化为完全图,然后找把它变成非强连通图需要去掉多少条边,但是应该怎么处理呢…… ...
- HDU 4635:Strongly connected(强连通)
http://acm.hdu.edu.cn/showproblem.php?pid=4635 题意:给出n个点和m条边,问最多能添加几条边使得图不是一个强连通图.如果一开始强连通就-1.思路:把图分成 ...
- hdu 4635 Strongly connected 强连通缩点
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4635 题意:给你一个n个点m条边的图,问在图不是强连通图的情况下,最多可以向图中添多少条边,若图为原来 ...
随机推荐
- proxy 利用get拦截,实现一个生成各种DOM节点的通用函数dom。
const dom = new Proxy({}, { get(target, property) { return function(attrs = {}, ...children) { const ...
- Java连接Oracle数据库的示例代码
最基本的Oracle数据库连接代码(只针对Oracle11g): 1.右键项目->构建路径 ->配置构建路径,选择第三项“库”,然后点击“添加外部Jar”,选择 “D:\Oracle\ap ...
- Java并发框架——AQS堵塞队列管理(一)——自旋锁
我们知道一个线程在尝试获取锁失败后将被堵塞并增加等待队列中,它是一个如何的队列?又是如何管理此队列?这节聊聊CHL Node FIFO队列. 在谈到CHL Node FIFO队列之前,我们先分析这样 ...
- Firebase远程更新应用
能打造出色的应用不意味着一定能在商业上取得成功,两者之间还有许多工作要做,绝不能简单发布应用后就宣告“收工”.您需要能迅速根据用户反馈作出调整.测试新功能,以及向用户提供他们最关注的内容. Fireb ...
- jquery模仿css3延迟效果
HTML <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta ...
- json的js和C#操作
C#端的WebService接口接收json格式数据,处理后以json格式返回result using System; using System.Collections.Generic; using ...
- OC——UIlabel text的常规应用
UILabel *downloader = [[UILabel alloc]init]; NSString *downloadCount = [[LibraryArr objectAtIndex:in ...
- c#窗体的传值方法
了解了窗体的显示相关知识,接着总结一下窗体的传值方法: .通过构造函数 特点:传值是单向的(不可以互相传值),实现简单 实现代码如下: 在窗体Form2中 int value1; ...
- Spark配置&启动脚本分析
本文档基于Spark2.0,对spark启动脚本进行分析. date:2016/8/3 author:wangxl Spark配置&启动脚本分析 我们主要关注3类文件,配置文件,启动脚本文件以 ...
- __m128i的理解[转]
__m128i被称为128bits的整数,当我们对其赋值时,调用 __m128i _mm_set1_epi32(int i) Sets the four signed 32-bit integer v ...