HDU 6165 FFF at Valentine

题目大意:给出一个有向图,问你这个图中是否对于任意两点\(u,v\),都至少满足\(u\to v\)(\(u\)可到达\(v\),下同)或\(v\to u\)中的一个。

一看就是套路的图论题,我们先把边连起来。

考虑一个很基本的性质:在一个强连通分量的点两两可达

于是肯定先Tarjan缩一波点。然后我们得到了一个DAG

接下来就是考虑是否有两个点(当然是缩点之后的了)互不可达

这个可以直接跑一边拓扑排序。然后看一下是否在某个时刻有两个点的入度为零即可。

CODE

#include<cstdio>
#include<cctype>
#include<cstring>
using namespace std;
const int N=1005;
struct edge
{
    int to,next;
}e[N*6],ne[N*6];
int head[N],nhead[N],t,n,m,x,y,cnt,tot,sum,dfn[N],low[N],col[N],stack[N],ru[N],q[N],top;
bool vis[N];
inline char tc(void)
{
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
    x=0; char ch; while (!isdigit(ch=tc()));
    while (x=(x<<3)+(x<<1)+ch-‘0‘,isdigit(ch=tc()));
}
inline void add(int x,int y)
{
    e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;
}
inline void nadd(int x,int y)
{
    ne[++cnt].to=y; ne[cnt].next=nhead[x]; nhead[x]=cnt;
}
inline void clear(void)
{
    memset(head,-1,sizeof(head)); memset(e,-1,sizeof(e));
    memset(nhead,-1,sizeof(nhead)); memset(ne,-1,sizeof(ne));
    memset(dfn,0,sizeof(dfn)); memset(vis,0,sizeof(vis));
    memset(col,0,sizeof(col)); memset(ru,0,sizeof(ru));
    cnt=tot=sum=top=0;
}
inline int min(int a,int b)
{
    return a<b?a:b;
}
inline void Tarjan(int now)
{
    dfn[now]=low[now]=++tot; vis[now]=1; stack[++top]=now;
    for (register int i=head[now];i!=-1;i=e[i].next)
    if (!dfn[e[i].to]) Tarjan(e[i].to),low[now]=min(low[now],low[e[i].to]);
    else if (vis[e[i].to]) low[now]=min(low[now],dfn[e[i].to]);
    if (dfn[now]==low[now])
    {
        vis[now]=0; col[now]=++sum;
        while (now!=stack[top])
        {
            vis[stack[top]]=0; col[stack[top--]]=sum;
        } --top;
    }
}
inline bool top_sort(void)
{
    register int i,H=0,T=0;
    for (i=1;i<=sum;++i)
    if (!ru[i]) q[++T]=i;
    while (H<T)
    {
        if (T-H>1) return 0;
        int now=q[++H];
        for (i=nhead[now];i!=-1;i=ne[i].next)
        if (!(--ru[ne[i].to])) q[++T]=ne[i].to;
    }
    return 1;
}
int main()
{
    //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    register int i,j; read(t);
    while (t--)
    {
        clear(); read(n); read(m);
        for (i=1;i<=m;++i)
        read(x),read(y),add(x,y);
        for (i=1;i<=n;++i)
        if (!dfn[i]) Tarjan(i);
        for (cnt=0,i=1;i<=n;++i)
        for (j=head[i];j!=-1;j=e[j].next)
        if (col[i]!=col[e[j].to]) nadd(col[i],col[e[j].to]),++ru[col[e[j].to]];
        if (top_sort()) puts("I love you my love and our love save us!"); else puts("Light my fire!");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/cjjsb/p/9415829.html

时间: 2024-10-12 12:28:30

HDU 6165 FFF at Valentine的相关文章

2017 Multi-University Training Contest - Team 9 1005&amp;&amp;HDU 6165 FFF at Valentine【强联通缩点+拓扑排序】

FFF at Valentine Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1060    Accepted Submission(s): 506 Problem Description At Valentine's eve, Shylock and Lucar were enjoying their time as any oth

HDU 6165 FFF at Valentine(Tarjan缩点+拓扑排序)

FFF at Valentine Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 575    Accepted Submission(s): 281 Problem Description At Valentine's eve, Shylock and Lucar were enjoying their time as any oth

[HDOJ6165] FFF at Valentine(强联通分量,缩点,拓扑排序)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6165 题意:问一个有向图中是否有任意两点可以到达. 读错题就彻底输了,读成判断是否有任意条路,使得经过所有点并且每条边最多走一次. 强联通缩点,然后维护拓扑序,假如拓扑序中有两个以上点入度为0,那么这几个点之间就不能互相到达了. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 namespace fastIO { 5 #define BU

hdu 6165

题意:n,m,n个点,m条边,问对于任意2个位置,是否可以从一个点到达另一个点 思路:缩点后,预处理出,每一个联通块能到达的联通块. 1 #include<bits/stdc++.h> 2 using namespace std; 3 #pragma comment(linker, "/STACK:102400000,102400000") 4 const int N=40003; 5 const int M=40003; 6 7 struct node 8 { 9 int

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") #defi

Valentine&#39;s Day Round 1001.Ferries Wheel(hdu 5174)解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5174 题目意思:给出 n 个人坐的缆车值,假设有 k 个缆车,缆车值 A[i] 需要满足:A[i−1]<A[i]<A[i+1](1<i<K).现在要求的是,有多少人满足,(他坐的缆车的值 + 他左边缆车的值) % INT_MAX == 他右边缆车的值. 首先好感谢出题者的样例三,否则真的会坑下不少人.即同一部缆车可以坐多个人.由于缆车的值是唯一的,所以可以通过排序先排出缆车的位置.求出

Valentine&#39;s Day Round hdu 5176 The Experience of Love [好题 带权并查集 unsigned long long]

传送门 The Experience of Love Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 221    Accepted Submission(s): 91 Problem Description A girl named Gorwin and a boy named Vivin is a couple. They arriv

hdu 4719 Oh My Holy FFF(线段数+dp)

题目链接:hdu 4719 Oh My Holy FFF 题目大意:队伍里有n个人,给出每个人的身高,他们按照顺序排列,现在要将这n个人分成若干组,每一组的人数不得大于l,并且第i组的最后一个人的身高一定要大于第i?1组的最后一个人的身高.要求最后的权值最大,权值计算方法在题目中,k为组号. 解题思路:dp[i]表示以第i个人作为结尾的最大权值,那么dp[i]肯定是从前面的l-1个中转移过来的,即dp[i]=dp[j]+h[i]2?h[j] 要求h[i]>h[j]. 但是这样的复杂度为o(n2)

hdu 4719 Oh My Holy FFF(dp线段树优化)

Oh My Holy FFF Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 848    Accepted Submission(s): 219 Problem Description N soldiers from the famous "*FFF* army" is standing in a line, from le