题目链接:点击打开链接

题意:

给定n个点m条边的无向图

问图中是否存在 有且仅有一个简单环和一些树,且这些树的root都在这个简单环上。

瞎写了个点双。

==

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <queue>
#include <vector>
#include <set>
using namespace std;
#define N 105
#define M 100005
#define inf 10000000
struct Edge{
int from,to,next;
}edge[2*M];
int head[N],edgenum;
int Low[N],DFN[N],Stack[N];//Belong数组的值是1~block
int Index,top;
int Belong[N],block;//新图的连通块标号(1~block)
bool Instack[N];
int bridge; //割桥数量
vector<int> bcc[N];
void addedge(int u,int v){
Edge E={u,v,head[u]}; edge[edgenum]=E; head[u] = edgenum++;
Edge E2={v,u,head[v]};edge[edgenum]=E2;head[v] = edgenum++;
}
void Tarjan(int u,int pre){
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
for(int i = head[u]; ~i ;i = edge[i].next){
v = edge[i].to;
// 假设重边有效的话以下这句改成: if(v == pre && pre_num == 0){pre_num++;continue;} pre_num在for上面定义 int pre_num=0;
if( v == pre )continue;
if( !DFN[v] ){
Tarjan(v,u);
if(Low[u] > Low[v])Low[u] = Low[v];
if(Low[v] > Low[u])
bridge++;
}
else if(Instack[v] && Low[u] > DFN[v])Low[u] = DFN[v];
}
if(Low[u] == DFN[u]){
block++;
bcc[block].clear();
do{
v = Stack[--top];
Instack[v] = false;
Belong[v] = block;
bcc[block].push_back(v);
}while( v != u );
}
}
void work(int l, int r){
memset(DFN,0,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
Index = top = block = bridge = 0;
for(int i = l; i <= r; i++)if(!DFN[i])Tarjan(i,i);
}
vector<int>G[N];
void suodian(){
for(int i = 1; i <= block; i++)G[i].clear();
for(int i = 0; i < edgenum; i+=2){
int u = Belong[edge[i].from], v = Belong[edge[i].to];
if(u==v)continue;
G[u].push_back(v), G[v].push_back(u);
}
}
void init(){edgenum = 0; memset(head,-1,sizeof(head));} int n, m, vis[N], siz[N], f[N];
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void Union(int x, int y){
int fx = find(x), fy = find(y);
if(fx==fy)return;
if(fx>fy)swap(fx,fy); f[fx] = fy;
}
bool dfs(int u){
vis[u] = 1;
bool ok = true;
for(int i = 0; i < G[u].size(); i++)
{
int v = G[u][i]; if(vis[v])continue;
if(bcc[v].size()>1)ok = false;
if(dfs(v)==false)ok = false;
}
return ok;
}
set<int>myset;
bool solve(){
int i, u, v;
init();
for(i = 1; i <= n; i++)f[i] = i;
while(m--){
scanf("%d %d",&u,&v);
addedge(u, v);
Union(u,v);
}
myset.clear();
for(i = 1; i<= n; i++)myset.insert(find(i));
if(myset.size()>1)return false;
work(1, n);
suodian();
memset(vis, 0, sizeof vis);
memset(siz, 0, sizeof siz);
for(i = 0; i < edgenum; i+=2)
siz[u]+= (Belong[edge[i].from]==Belong[edge[i].to]); for(i = 1; i <= block; i++) if(!vis[i] && bcc[i].size()>1 && bcc[i].size()==siz[i] && G[i].size()>=3)
if(dfs(i))return true; return false;
}
int main(){
while(~scanf("%d %d", &n, &m))
solve() ? puts("FHTAGN!") : puts("NO");
return 0;
}
/*
6 6
1 2
2 3
3 1
4 5
5 6
6 4 */

Codeforces 104C Cthulhu dfs暴力 || 点双连通缩点的更多相关文章

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

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

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

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

  3. UVA 10972 RevolC FaeLoN(边-双连通+缩点)

    很好的一道图论题,整整撸了一上午... 题意是给定一个无向图,要求将所有边变为有向边,求最少加入多少条有向边,使得该图强连通?这里先假设一个问题:给定一个无向子图,该子图具有怎样的性质才能使得将其无向 ...

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

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

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

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

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

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

  7. Hdu4005-The war(双连通缩点)

    In the war, the intelligence about the enemy is very important. Now, our troop has mastered the situ ...

  8. UVA-10972 RevolC FaeLoN (边双连通+缩点)

    题目大意:将n个点,m条边的无向图变成强连通图,最少需要加几条有向边. 题目分析:所谓强连通,就是无向图中任意两点可互达.找出所有的边连通分量,每一个边连通分量都是强连通的,那么缩点得到bcc图,只需 ...

  9. hdu4612(双连通缩点+树的直径)

    传送门:Warm up 题意:询问如何加一条边,使得剩下的桥的数目最少,输出数目. 分析:tarjan缩点后,重新建图得到一棵树,树上所有边都为桥,那么找出树的直径两个端点连上,必定减少的桥数量最多, ...

随机推荐

  1. Yii1 获取当前请求的url

    echo Yii::app()->getRequest()->getUrl();

  2. 查询mysql所有表数据、字段信息

    根据库名获取所有表的信息 SELECT * FROM information_schema.`TABLES` WHERE TABLE_SCHEMA = 'erp'; 根据库名获取所有表名称和表说明 S ...

  3. python基础知识12-异常

    几个命令: sudo apt install tree tree 当前目录以树形结构展示出来. tree a 查看a内的所有目录.也可以跟绝对路径. a = input('请输入您的密码') 将用户输 ...

  4. mac 终端path配置出错,命令无法使用

    mac 命令行中修改path的时候,不小心把path修改错了,而且还 source 了,然后发现只能使用 cd 命令,ls vi 命令都不能使用了. 解决办法,执行下面的语句 export PATH= ...

  5. 完善的IaaS云服务的个人理解

    此文已由作者王盼授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 前情提要 本文仅讨论云主机(虚拟机).云硬盘(块存储).云网络(普通虚拟网络或SDN)相关的IaaS服务,相关 ...

  6. HDU 5076 Memory

    Memory Time Limit: 4000ms Memory Limit: 262144KB This problem will be judged on HDU. Original ID: 50 ...

  7. php 数据库的增删改查

    <!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>&l ...

  8. FZU-1881-Problem 1881 三角形问题,打表二分查找~~

    B - 三角形问题 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Descripti ...

  9. windows 2008、2012防火墙添加入站规则教程(端口例外)

    windows2008.2012的设置方法基本一样,以下是以windows2008为例做添加80端口的步骤. 1.依次点“控制面板”→“系统和安全”→“windows防火墙”→“高级设置”,打开“高级 ...

  10. LA 3890 半平面交

    二分查询答案,判断每一个新形成的向量合在一块能否形成半平面交 #include <iostream> #include <cstdio> #include <cstrin ...