Codeforces 104C Cthulhu dfs暴力 || 点双连通缩点
题目链接:点击打开链接
题意:
给定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暴力 || 点双连通缩点的更多相关文章
- 边双连通缩点+树dp 2015 ACM Arabella Collegiate Programming Contest的Gym - 100676H
http://codeforces.com/gym/100676/attachments 题目大意: 有n个城市,有m条路,每条路都有边长,如果某几个城市的路能组成一个环,那么在环中的这些城市就有传送 ...
- hdu 4612 Warm up 双连通缩点+树的直径
首先双连通缩点建立新图(顺带求原图的总的桥数,事实上因为原图是一个强连通图,所以桥就等于缩点后的边) 此时得到的图类似树结构,对于新图求一次直径,也就是最长链. 我们新建的边就一定是连接这条最长链的首 ...
- UVA 10972 RevolC FaeLoN(边-双连通+缩点)
很好的一道图论题,整整撸了一上午... 题意是给定一个无向图,要求将所有边变为有向边,求最少加入多少条有向边,使得该图强连通?这里先假设一个问题:给定一个无向子图,该子图具有怎样的性质才能使得将其无向 ...
- poj 3352 Road Construction【边双连通求最少加多少条边使图双连通&&缩点】
Road Construction Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10141 Accepted: 503 ...
- POJ 3177 Redundant Paths (边双连通+缩点)
<题目链接> <转载于 >>> > 题目大意: 有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新 ...
- POJ - 3177 Redundant Paths (边双连通缩点)
题意:在一张图中最少可以添加几条边,使其中任意两点间都有两条不重复的路径(路径中任意一条边都不同). 分析:问题就是最少添加几条边,使其成为边双连通图.可以先将图中所有边双连通分量缩点,之后得到的就是 ...
- Hdu4005-The war(双连通缩点)
In the war, the intelligence about the enemy is very important. Now, our troop has mastered the situ ...
- UVA-10972 RevolC FaeLoN (边双连通+缩点)
题目大意:将n个点,m条边的无向图变成强连通图,最少需要加几条有向边. 题目分析:所谓强连通,就是无向图中任意两点可互达.找出所有的边连通分量,每一个边连通分量都是强连通的,那么缩点得到bcc图,只需 ...
- hdu4612(双连通缩点+树的直径)
传送门:Warm up 题意:询问如何加一条边,使得剩下的桥的数目最少,输出数目. 分析:tarjan缩点后,重新建图得到一棵树,树上所有边都为桥,那么找出树的直径两个端点连上,必定减少的桥数量最多, ...
随机推荐
- Swift 中的Range和NSRange不同
Swift中的Ranges和Objective-C中的NSRange有很大的不同,我发现在处理Swift中Ranges相关的问题的时候,总是要花费比我想象的更多的时间.不过,现在回过头来看看,发现Sw ...
- react随笔-1(为什么在react使用jq无法正确渲染组件位置)
今天心血来潮,打开了sublime想玩玩react,然后大家都知道的先引入一大串 就是在百度静态资源库里找到的. 然后贴html代码 对的,没错,就这么一行,毕竟只是测试嘛 然后js代码 大家一定要注 ...
- vue 父子组件的加载顺序
一.加载渲染过程 父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount ...
- jquery-closest
1.closest() 本例演示如何通过 closest() 完成事件委托.当被最接近的列表元素或其子后代元素被点击时,会切换黄色背景: $( document ).bind("click& ...
- [题解] codevs 1486 愚蠢的矿工
http://codevs.cn/problem/1486/ 我们比较熟悉二叉树,题目中给出的是一棵多叉树,我们需要将这可二叉树改造成二叉树. 二叉树可以为这样的: 父亲结点左边储存儿子,右边储存兄弟 ...
- HNOI2006 花仙子的魔法
题目描述 题解: 考试的时候手画打表,然后半个小时磨了个式子:$$f[i][j]=f[i-1][j-1]+f[i][j-1]$$ 交上去$A$的时候都蒙了. 考后才知道原因. 考虑$n$维空间内原来有 ...
- Windows 命令收集
定时关机命令:schtasks /create /tn "关机" /tr "shutdown /s" /sc once /st 23:55
- docker守护式容器运行管理
docker守护式容器适合运行应用程序和服务 以交互方式进入容器 docker run -it centos /bin/bash 以交互方式进入 并设置镜像名称和运行后的主机名称 退出交互式容器并让 ...
- Counting Kangaroos is Fun 求最少可见袋鼠数
Description There are n kangaroos with pockets. Each kangaroo has a size (integer number). A kangaro ...
- POJ1703-Find them, Catch them 并查集构造
Find them, Catch them 好久没有做并查集的题,竟然快把并查集忘完了. 题意:大致是有两个监狱,n个 ...