hdu6165 缩点,dfs

hdu6165    FFF at Valentine

题意:给出一个有向图,问任意两个点 a、b,是否可以从a到b,或者从b到a。

tags:主要是题意有点绕。。 只要 tarjan 缩点成 DAG图,再 dfs 判断一下在 DAG 图中是否有一条路径包含了所有点。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 6005;

int n, m;
struct Edge{ int from, to, next; } e[N*2];
int Stack[N<<2], dfn[N], low[N], Belong[N], sz[N], head[N];
bool instack[N];
int top, tot, sum, tot1;
void Addedge(int u,int v) { e[tot]={u, v, head[u]}; head[u]=tot++; }
void Tarjan(int u)
{
    dfn[u]=low[u]=++tot1;
    Stack[top++]=u, instack[u]=1;
    for(int i=head[u]; i!=-1; i=e[i].next) {
        int v=e[i].to;
        if(dfn[v]==0) {
            Tarjan(v);
            low[u]=min(low[u], low[v]);
        }
        else if(instack[v]) low[u]=min(low[u], dfn[v]);
    }
    if(dfn[u]==low[u]) {
        sum++;
        while(top!=0) {
            int en=Stack[--top];
            instack[en]=0;
            Belong[en]=sum;
            sz[sum]++;
            if(en==u) break;
        }
    }
}
vector<int > G[N<<1];
int in[N], s1;
void Init()
{
    mes(head, -1);  mes(Stack, 0);  mes(dfn, 0);
    mes(Belong, 0);  mes(sz, 0);  mes(instack, false);
    mes(low, 0);
    mes(in, 0);
    rep(i,0,(N<<1)-1) G[i].clear();
    sum = tot = tot1 = top = s1 = 0;
}
bool dfs(int u)
{
    ++s1;
    if(s1==sum) return true;
    for(int i=0; i<G[u].size(); ++i)
    {
        if(dfs(G[u][i])) return true;
    }
    --s1;
    return false;
}
int main()
{
    int T;  scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &n, &m);
        Init();
        int u, v;
        rep(i,1,m)
        {
            scanf("%d%d", &u, &v);
            Addedge(u, v);
        }
        rep(i,1,n) if(dfn[i]==0) Tarjan(i);
        bool flag=0;
        rep(i,0,tot-1)
        {
            u=Belong[e[i].from], v=Belong[e[i].to];
            if(u!=v)  G[u].PB(v), ++in[v];
        }
        int ro, num=0;
        rep(i,1,sum) if(in[i]==0) ro=i, ++num;
        if(num>1) flag=1;
        else if(!dfs(ro)) flag=1;
        if(flag==0) puts("I love you my love and our love save us!");
        else puts("Light my fire!");
    }

    return 0;
}
时间: 2024-10-14 05:48:18

hdu6165 缩点,dfs的相关文章

hihoCoder#1185 : 连通性&#183;三 tarjan求强联通分量 缩点 dfs/拓扑排序求路径和最大值

题目链接: http://hihocoder.com/problemset/problem/1185# 题意: n个点,每个点有一个权值,m条有向边,从1出发,每走到一个点, 就吃掉这个点的草,当没有可以到达的草场或是能够到达的草场都已经被吃光了之后就要返回到1了.求最多可以吃掉多少草. 思路: 提示里面讲的挺好的 如果草场是一个强连通图,那么我们只要走到任意一点,就可以把其他所有的草场都走一遍,并且可以选择任意一个点作为终点.所以把强联通块缩成一个点 因为一个强连通块会被缩成一个点,那么我们可

HDU 3639 Hawk-and-Chicken tarjan缩点+dfs

题意:投票,投票可以传递,当一个人投票时,要把此人的得票数全给被投的那个人,问最后按升序输出得票数最高的人. 想法:显然在一个连通块内的所有点的得票数都是一样的,即:块内点数-1,(1:是他自己本身).所以先要tarjan缩点,然后求出每一个块可以由几个块到达(这里可以反向建边dfs).最后输出最大得票数的人即可. #include<iostream> #include<cstring> #include<cstdio> #include<stack> #i

【NOIP模拟题】Graph(tarjan+dfs)

似乎我搞得太复杂了? 先tarjan缩点然后dfs就行了QAQ. (我不说我被一个sb错调了半个小时....不要以为缩点后dfs就可以肆无忌惮的不加特判判vis了.. bfs的做法:减反图,然后从大到小枚举(贪心),标记即可 #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorit

Codeforces B. Mouse Hunt(强连通分解缩点)

题目描述: Mouse Hunt time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Medicine faculty of Berland State University has just finished their admission campaign. As usual, about 80%of applicants a

UVA 11770 Lighting Away

RunID User Problem Result Memory Time Language Length Submit Time 2482977 zhyfzy J Accepted 0 KB 138 ms C++ 4.8.2 2322 B 2014-07-24 15:18:54 [题目大意] 一个有向图,每对一个结点操作,就可以触发连锁反应,使得该结点及它直接或间接指向的点均获得标记,问至少需要操作多少个结点使得所有结点获得标记 [题解] 缩点+DFS 首先能想到入度为0的点一定需要操作,但是

【图论】双连通总结

双连通总结 这类问题分为,边-双连通,点-双连通 边双连通 边双连通,求出来后,连接没一个双连通的分量的就是割边,因此可以缩点成一棵树,把问题转化为在树上搞,割边的定义为:去掉这条边后图将不连通 基本这类题都一个解法,求双连通分量,然后缩点成树,进行操作 或者就是直接要求割边,做跟割边相关的操作 模板: #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #

c2java 第7篇 图的连通分量,关节点和桥

图的连通分量,关节点和桥 ==== 对于有向图,我们称其一个子图是强连通分量,是指任意两点u,v, 都有两条路径u到v和v到u. 对于连通无向图,我门称其一个子图是双连通分量,是指任意两点u,v,存在一个圈包含u,v.与无向图相关联的还有关节点x,是指去掉x,图不连通:桥(u,v)是指去掉这条边,图不连通. 求解算法的要义在于首先要理解: 树边-前向边-后向边-交叉边 "Consider what happens when a depth-first search is performed on

洛谷 P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm

P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm 题目描述 Every year in Wisconsin the cows celebrate the USA autumn holiday of Halloween by dressing up in costumes and collecting candy that Farmer John leaves in the N (1 <= N <= 100,000) stalls conven

hdu 2242 无向图/求用桥一分为二后使俩个bcc点权值和之差最小并输出 /缩点+2次新图dfs

题意如标题所述, 先无向图缩点,统计出每个bcc权,建新图,然后一遍dfs生成树,标记出每个点(新图)以及其子孙的权值之和.这样之后就可以dfs2来枚举边(原图的桥),更新最小即可. 调试了半天!原来是建老图时候链式前向星和新图的vector<vector< int>>俩种存图搞乱了!!!不可原谅!哎!愚蠢!愚不可及!提交后1A. 后来百度之后,发现说是用树形dp,看了代码解法,竟然和我的是一样的算法..原来这种算法可以叫树形dp...的确有点dp味道..不过感觉不太浓.. 以后多