SDUT 2604 Thrall’s Dream (单连通的判断)

大意:给定一些有向图间的关系问任意两点是不是可达的。

思路:Tarjan后直接看入度和出度为0的数量关系,如果大于1则肯定是不可能,相连通的。

#include<map>
#include<queue>
#include<cmath>
#include<cstdio>
#include<stack>
#include<iostream>
#include<cstring>
#include<algorithm>
#define LL int
#define inf 0x3f3f3f3f
#define eps 1e-8
#include<vector>
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1

using namespace std;

const int Ma = 10100;
struct node{
    int to,w,next;
}q[Ma];
int head[Ma],dfn[Ma],num[Ma],du[Ma],stk[Ma],vis[Ma],low[Ma];
int cnt,top,tim,scc,out[Ma],in[Ma];

bool mp[1100][1100];
void Add(int a,int b){
    q[cnt].to = b;
    q[cnt].next = head[a];
    head[a] = cnt++;
}
void init(){
    scc =  cnt = top = 0;
    tim =  1;
    memset(head,-1,sizeof(head));
    memset(dfn,0,sizeof(dfn));
    memset(num,0,sizeof(num));
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    memset(vis,0,sizeof(vis));
    memset(low,0,sizeof(low));
    memset(mp,false,sizeof(mp));
}
void Tarjan(int u){
    low[u] = dfn[u] = tim++;
    vis[u] = 1;
    stk[top++] = u;
    for(int i = head[u]; ~i ; i = q[i].next){
        int v = q[i].to;
        if(!vis[v]){
            Tarjan(v);
            low[u] = min(low[u],low[v]);
        }
        else
            low[u] = min(low[u],dfn[v]);
    }

    if(low[u] == dfn[u]){//找到极大联通分量
        scc++;
        while(top > 0&&stk[top] != u){
            top --;
            vis[stk[top] ] = 2;
            num[stk[top] ] = scc;
        }
    }

}
int main(){
    int n,m,i,j,k,a,b,c,cla;
    scanf("%d",&cla);
    for(int zu = 1;zu <=cla;++ zu){
        scanf("%d%d",&n,&m);
        init();
        for(i = 0;i <m;++ i){
            scanf("%d%d",&a,&b);
            Add(a,b);
        }
        for(i = 1;i <= n;++ i)
            if(!dfn[i])
                Tarjan(i);
        bool bj = false;
        for(i = 1;i <= n;++ i){
            for(j = head[i];~j; j = q[j].next){
                int v = q[j].to;
                if(num[i] != num[v]){
                    out[num[i] ]++;
                    in[num[v] ]++;
                }
            }

        }
        int ans1,ans2;
        ans1 = ans2 =0;
        for(i = 1;i <= scc;++ i){
            if(in[i]==0)
                ans1++;
            if(out[i]==0)
                ans2++;
            cout<<i<<endl;
        }
        printf("Case %d: ",zu);
        if(ans1>1||ans2>1){
            puts("The Burning Shadow consume us all");
        }
        else{
            puts("Kalimdor is just ahead");
        }
    }
    return 0;
}
时间: 2024-10-26 22:57:08

SDUT 2604 Thrall’s Dream (单连通的判断)的相关文章

[ACM] SDUT 2604 Thrall’s Dream

Thrall's Dream Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 We never paid any heed to the ancient prophecies, like fools we clung to the old hatreds, and fought as we had for generations. Until one day the sky rained fire, and a new ene

sdutoj Thrall’s Dream

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2604 Thrall’s Dream Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 We never paid any heed to the ancient prophecies, like fools we clung to the old hatreds, and fought

第四届山东省赛 Thrall’s Dream(BFS+vector)

2218: Thrall's Dream Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 253  Solved: 72 [Submit][Status][Web Board] Description We never paid any heed to the ancient prophecies, like fools we clung to the old hatreds, and fought as we had for generation

sdut Thrall’s Dream(判断任意两点是否联通)

题意:给一张无向图,判断任意两点是否联通: 思路:bfs枚举个点,逐个遍历: #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<queue> using namespace std; int con[2005][2005]; vector<short> v[2005]; int n,m; int judge() { int

SDUT OJ 2138 图结构练习——BFSDFS——判断可达性

#include<iostream> #include<memory.h> using namespace std; int visit[1001]; int t[1001][1001]; int k; int n; void dfs(int x,int n) { int i; visit[x]=1; if(x==1) { k++; return ; } for(i=1;i<=n;i++) { if(t[x][i]==1 && visit[i]==0) dfs

SDUT OJ 2140 图结构练习——判断给定图是否存在合法拓扑序列

#include<iostream> #include<memory.h> using namespace std; int tp[11][11],visit[11]; int main() { int n,m,i,j,k,s,o,c; int flag,count,a,b; while(cin>>n>>m) { s=1; o=0; count=0; memset(tp,0,sizeof(tp)); memset(visit,0,sizeof(visit))

POJ2411(Mondriaan&#39;s Dream)

题目链接:传送门 题目大意:用1*2大小的砖块去铺满n*m大小的地面,有多少种方案 题目思路:因为1<=n,m<=11,并且砖块是1*2,故可以用二进制思想,也就是状态压缩DP,其中矩阵中为0的元素表示当前位置竖着放一块砖,而连着 两个1表示横着放一块砖(状态压缩真的很奇妙) #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <

poj 2411 Mondriaan&#39;s Dream(状态压缩+dp)

 题意:用1*2砖块铺满n*m的房间. 思路转自:http://www.cnblogs.com/scau20110726/archive/2013/03/14/2960448.html 因为这道题输入范围在11*11之间,所以可以先打表直接输出.......... 状态压缩DP 经典覆盖问题,输入n和m表示一个n*m的矩形,用1*2的方块进行覆盖,不能重叠,不能越出矩形边界,问完全覆盖完整个矩形有多少种不同的方案 其中n和m均为奇数的话,矩形面积就是奇数,可知是不可能完全覆盖的.接着我们来看

matlab练习程序(矩形变换为单连通形状)

变换使用的模板必须是单连通的,如果在模板中打个结,这里的程序就处理不了了. 虽然非单连通模板也有办法处理,不过不是这里要讨论的. 这里用到的方法和矩形变换为圆那片文章中用的方法几乎一样,变换前后像素按比例缩减,不过在判断弧度和图像边界到模板中心距离时略有不同. 变换为圆时弧度可以直接计算出来,而变换为任意形状只能算出一个最小相似值. 至于图像边界到模板中心距离只能分八种情况判断了,处理圆时可以根据对称性简化程序,这里似乎没有什么好办法简化. 变换细节上,那篇文章中使用的是正向插值,这里使用正向插