很好的一道图论题,整整撸了一上午。。。

题意是给定一个无向图,要求将所有边变为有向边,求最少加入多少条有向边,使得该图强连通?这里先假设一个问题:给定一个无向子图,该子图具有怎样的性质才能使得将其无向边都变为有向边后强连通?显然是边-双连通!边连通的性质就是任意两点间存在边部重合的两条路,所以你懂的。。。

所以这个题的解法就是:求出原图的边-双连通分量后缩点,变成一棵bcc树。现在问题就变成了:给定一棵无向树,添加最少边使得该图强连通?这个问题在纸上画画大概能推出来。。。sum为所有叶子节点的个数,ans便是(sum+1)/ 2。。。求边-双连通的方法大白书说的很清楚了,先dfs标记所有桥,然后再dfs1一次,途中不经过桥就行。

还有一点,原图中可能本来就有孤立点(如sample 2中的点10),那么它所在的bcc点的度数为0,所以要在缩点后处理的时候处理一下孤立点。。。

另外还有一点。。。当原图本来就双连通的时候要特判ans=0。。。

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<fstream>
#include<sstream>
#include<map>
#include<set>
#define FF(i, a, b) for(int i=a; i<b; i++)
#define FD(i, a, b) for(int i=a; i>=b; i--)
#define REP(i, n) for(int i=0; i<n; i++)
#define CLR(a, b) memset(a, b, sizeof(a))
#define LL long long
#define PB push_back
#define debug puts("**debug**")
using namespace std; const int maxn = 1111;
int n, m, u, v;
int pre[maxn], low[maxn], dfs_clock, bcc_cnt, bccno[maxn], d[maxn];
struct Edge
{
int to, flag;
};
vector<int> G[maxn];
vector<Edge> edges; inline void init()
{
CLR(d, 0);
REP(i, n) G[i].clear(); edges.clear();
} void add(int u, int v)
{
edges.PB((Edge){v, 0});
edges.PB((Edge){u, 0});
int nc = edges.size();
G[u].PB(nc-2);
G[v].PB(nc-1);
} int dfs(int u, int fa)
{
int lowu = pre[u] = ++dfs_clock;
int nc = G[u].size();
REP(i, nc)
{
int v = edges[G[u][i]].to;
if(!pre[v])
{
int lowv = dfs(v, u);
lowu = min(lowu, lowv);
if(lowv > pre[u]) edges[G[u][i]].flag = 1, edges[G[u][i]^1].flag = 1; //标记所有桥
}
else if(pre[v] < pre[u] && v != fa) lowu = min(lowu, pre[v]);
}
return low[u] = lowu;
} void dfs1(int u)
{
bccno[u] = bcc_cnt;
int nc = G[u].size();
REP(i, nc)
{
int v = edges[G[u][i]].to;
if(!bccno[v] && edges[G[u][i]].flag != 1) dfs1(v);//不经过桥
}
} void find_bcc()
{
CLR(pre, 0); CLR(bccno, 0);
dfs_clock = bcc_cnt = 0;
REP(i, n) if(!pre[i]) dfs(i, -1);
REP(i, n) if(!bccno[i]) bcc_cnt++, dfs1(i);
} int main()
{
while(~scanf("%d%d", &n, &m))
{
init();
int ans = 0;
REP(i, m)
{
scanf("%d%d", &u, &v); u--; v--;
add(u, v);
}
find_bcc();
if(bcc_cnt == 1)
{
puts("0");
continue;
}
REP(u, n) //缩点
{
int nc = G[u].size();
REP(i, nc)
{
int v = edges[G[u][i]].to;
if(bccno[u] != bccno[v]) d[bccno[u]]++;
}
}
FF(i, 1, bcc_cnt+1)
{
if(d[i] == 0) ans += 2; //孤立点
if(d[i] == 1) ans++;
}
printf("%d\n", (ans+1)/2);
}
return 0;
}

UVA 10972 RevolC FaeLoN(边-双连通+缩点)的更多相关文章

  1. UVA 10972 - RevolC FaeLoN(边-双连通分量)

    UVA 10972 - RevolC FaeLoN option=com_onlinejudge&Itemid=8&page=show_problem&category=547 ...

  2. uva 10972 RevolC FaeLoN cdoj 方老师和农场

    //自己写的第一发tarjan 解:先进行双连通分解并缩点,分解后一定是一颗树,设叶节点个数为n那么答案就是(n+1)/2 关于双连通分量求解:在跑tarjan时判断每个点连向父节点的边是否是桥,如果 ...

  3. UVA - 10972 RevolC FaeLoN

    一道特别好的题qwq. 题目大意就是给你一个无向图,让你把边定向之后再加一些边使得这个图强连通,求最少需要加多少边. 一开始毫无头绪23333,数据范围让人摸不着头脑..... 然后开始画图,,,发现 ...

  4. UVA 10972 RevolC FaeLoN(边连通分量)

    坑了我一天的题目..跑了20ms挂了,就知道有个小毛病= = 无向图转有向图判强连通. 首先要知道什么样的无向图可以转化为强连通图?连通分量(环)自然是可以的:那么扩大范围(存在割顶),发现点连通分量 ...

  5. hdu 4612 Warm up 双连通缩点+树的直径

    首先双连通缩点建立新图(顺带求原图的总的桥数,事实上因为原图是一个强连通图,所以桥就等于缩点后的边) 此时得到的图类似树结构,对于新图求一次直径,也就是最长链. 我们新建的边就一定是连接这条最长链的首 ...

  6. 边双连通缩点+树dp 2015 ACM Arabella Collegiate Programming Contest的Gym - 100676H

    http://codeforces.com/gym/100676/attachments 题目大意: 有n个城市,有m条路,每条路都有边长,如果某几个城市的路能组成一个环,那么在环中的这些城市就有传送 ...

  7. POJ 3177 Redundant Paths (边双连通+缩点)

    <题目链接> <转载于 >>>  > 题目大意: 有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新 ...

  8. POJ - 3177 Redundant Paths (边双连通缩点)

    题意:在一张图中最少可以添加几条边,使其中任意两点间都有两条不重复的路径(路径中任意一条边都不同). 分析:问题就是最少添加几条边,使其成为边双连通图.可以先将图中所有边双连通分量缩点,之后得到的就是 ...

  9. poj 3352 Road Construction【边双连通求最少加多少条边使图双连通&&缩点】

    Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10141   Accepted: 503 ...

随机推荐

  1. PowerPC简单了解

    PowerPC相对于ARM优势: Powerpc芯片凭借其出色的性能和高度整合和技术先进特性在网络通信应用,工业控制应用,家用数字化,网络存储领域,军工领域,电力系统控制等都具有非常广泛的应用.由于P ...

  2. React 16 源码瞎几把解读 【三 点 二】 react中的fiberRoot

    〇.先来看看常用的常量 NoWork = 0 noTimeout = undefined HostRoot = 3 NoContext = 0b000; AsyncMode = 0b001; Stri ...

  3. openjudge-NOI 2.6-2000 最长公共子上升序列

    题目链接:http://noi.openjudge.cn/ch0206/2000/ 题解: 裸题,不解释(题目有毒) #include<cstdio> #include<algori ...

  4. C/C++——#和##操作符

    1. #操作符 使用阶段:预处理阶段,只有宏定义中使用(#define) 作用:将宏参数转换为字符串 示例: #define STRING(x) #x 2. ##操作符 使用阶段:预处理阶段,只有宏定 ...

  5. nginx 服务器篇

    Nginx 服务器类型 1. Web服务器 Web服务器用于提供HTTP(包括HTTPS)的访问,例如Nginx.Apache.IIS等. 2. 应用程序服务器 应用程序服务器能够用于应用程序的运行, ...

  6. 通过复制(拷贝)新建javaweb项目报错无法访问

    我们有时候为了方便,用eclipse在原来动态web项目上直接复制,粘贴项目,来形成以一个新的项目.可是运行的时候,它显示的url地址,还是原来的项目地址.初步判定,有可能是eclipse配置的问题. ...

  7. HTML 禁止显示input默认提示信息

    看问题 html代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  8. 深度学习方法(九):自然语言处理中的Attention Model注意力模型

    欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.NET/xbinworld. 技术交流QQ群:433250724,欢迎对算法.技术感兴趣的同学加入. 上一篇博文深度学习方法(八):Enc ...

  9. java 基础知识-数组的7种算法(排序、求和、最值、遍历...)

    遍历 遍历就是把这个数组的每个元素 显示出来 遍历的方法就是先定义这个数组的大小,然后用FOR循环来完成数组,例如 double[] score = new double[5]; Scanner in ...

  10. Templated Helper Methods(二)

      1.Label and Display Elements   2.Whole-Model Templated Helpers     3.Using Metadata to Control Edi ...