• poj2762 判断一个图中任意两点是否存在可达路径 也可看成DAG的最小覆盖点是否为1


     
    Going from u to v or from v to u?
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 17993   Accepted: 4816

    Description

    In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has n rooms, and one-way corridors connecting some rooms. Each time, Wind choose two rooms x and y, and ask one of their little sons go from one to the other. The son can either go from x to y, or from y to x. Wind promised that her tasks are all possible, but she actually doesn't know how to decide if a task is possible. To make her life easier, Jiajia decided to choose a cave in which every pair of rooms is a possible task. Given a cave, can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?

    Input

    The first line contains a single integer T, the number of test cases. And followed T cases.

    The first line for each case contains two integers n, m(0 < n < 1001,m < 6000), the number of rooms and corridors in the cave. The next m lines each contains two integers u and v, indicating that there is a corridor connecting room u and room v directly.

    Output

    The output should contain T lines. Write 'Yes' if the cave has the property stated above, or 'No' otherwise.

    Sample Input

    1
    3 3
    1 2
    2 3
    3 1
    

    Sample Output

    Yes


    题目大意就是给你张图,问你是否任意两点u,v 可以从u到v或者从v到u
    两种解法 先贴拓扑的
    另外有些数据
    1
    3 2
    1 2
    3 2

    1
    3 3
    1 2
    1 3
    2 3
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=1008;
    const int M=6008;
    int head[N],dfn[N],in[N],low[N],bl[N],q[N];
    int tot,cnt,scnt,n,m,l;
    bool instack[N];
    bool adj[N][N];
    struct node{
        int u,to,next;
    }e[M<<1];
    void init(){
        memset(dfn,0,sizeof(dfn));
        memset(instack,0,sizeof(instack));
        memset(in,0,sizeof(in));
        memset(head,-1,sizeof(head));
        memset(adj,0,sizeof(adj));
        l=tot=cnt=scnt=0;
    }
    void add(int u,int v){
        e[tot].u=u;e[tot].to=v;e[tot].next=head[u];head[u]=tot++;
    }
    void Tajan(int u){
        instack[u]=1;
        q[l++]=u;
        low[u]=dfn[u]=++cnt;
        for(int i=head[u];i+1;i=e[i].next){
            int v=e[i].to;
            if(!dfn[v]) {
                Tajan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(instack[v]&&low[u]>dfn[v]) low[u]=dfn[v];
        }
        if(low[u]==dfn[u]){
            int t;
            ++scnt;
            do{
                t=q[--l];
                instack[t]=0;
                bl[t]=scnt;
            }while(t!=u);
        }
    }
    bool Ju(int u){
        while(scnt--){
            int cont=0;
            for(int i=head[u];i+1;i=e[i].next){
                int v=e[i].to;
                --in[v];
                if(in[v]==0) {
                    cont++;u=v;
                }
            }
            if(cont>1) return 0;
        }
        return 1;
    }
    int main(){
        int T,u,v;
        for(scanf("%d",&T);T--;){
            scanf("%d%d",&n,&m);
            init();
            for(int i=1;i<=m;++i){
                scanf("%d%d",&u,&v);
                add(u,v);
            }
            for(int i=1;i<=n;++i)
                if(!dfn[i]) Tajan(i);
            memset(head,-1,sizeof(head));
            for(int i=0;i<tot;++i){
                u=e[i].u,v=e[i].to;
                if(bl[u]==bl[v]||adj[u][v]) continue;
                else {
                    adj[bl[u]][bl[v]]=1; // 注意这里
                    add(bl[u],bl[v]);
                    ++in[bl[v]];
                }
            }
            int cont=0,k;
            for(int i=1;i<=scnt;++i)
                if(!in[i]) {++cont;k=i;}
            if(cont>1) {puts("No");continue;}
            else {
                if(Ju(k)) puts("Yes");
                else puts("No");
            }
        }
    }
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    const int MAXN = 20010;
    const int MAXM = 100010;
    
    struct Edge{
        int to, next;
    }edge[MAXM];
    
    int head[MAXN], tot;
    int Low[MAXN], DFN[MAXN], Stack[MAXN], Belong[MAXN];
    int Index, top;
    int scc;
    bool Instack[MAXN];
    int num[MAXN];
    int n, m;
    
    void init() {
        tot = 0;
        memset(head, -1, sizeof(head));
    }
    
    void addedge(int u, int v) {
        edge[tot].to = v;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    
    void Tarjan(int u) {
        int v;
        Low[u] = DFN[u] = ++Index;
        Stack[top++] = u;
        Instack[u] = true;
        for (int i = head[u]; i != -1; i = edge[i].next) {
            v = edge[i].to;
            if (!DFN[v]) {
                Tarjan(v);
                if (Low[u] > Low[v]) Low[u] = Low[v];
            }
            else if (Instack[v] && Low[u] > DFN[v])
                Low[u] = DFN[v];
        }
        if (Low[u] == DFN[u]) {
            scc++;
            do {
                v = Stack[--top];
                Instack[v] = false;
                Belong[v] = scc;
                num[scc]++;
            } while (v != u);
        }
    }
    
    void solve() {
        memset(Low, 0, sizeof(Low));
        memset(DFN, 0, sizeof(DFN));
        memset(num, 0, sizeof(num));
        memset(Stack, 0, sizeof(Stack));
        memset(Instack, false, sizeof(Instack));
        Index = scc = top = 0;
        for (int i = 1; i <= n; i++)
            if (!DFN[i])
                Tarjan(i);
    }
    
    vector<int> g[MAXN];
    int linker[MAXN], used[MAXN];
    
    bool dfs(int u) {
        for (int i = 0; i < g[u].size(); i++) {
            int v = g[u][i];
            if (!used[v]) {
                used[v] = 1;
                if (linker[v] == -1 || dfs(linker[v])) {
                    linker[v] = u;
                    return true;
                }
            }
        }
        return false;
    }
    
    int hungary() {
        int res = 0;
        memset(linker, -1, sizeof(linker));
        for (int i = 1; i <= scc; i++) {
            memset(used, 0, sizeof(used));
            if (dfs(i)) res++;
        }
        return (scc - res)==1;
    }
    
    int main() {
        int cas;
        scanf("%d", &cas);
        while (cas--) {
            scanf("%d%d", &n, &m);
            init();
            int u, v;
            for (int i = 0; i < m; i++) {
                scanf("%d%d", &u, &v);
                addedge(u, v);
            }
            solve();
    
            for (int i = 0; i <= scc; i++) g[i].clear();
            for (int u = 1; u <= n; u++) {
                for (int i = head[u]; i != -1; i = edge[i].next) {
                    int v = edge[i].to;
                    if (Belong[u] != Belong[v])
                        g[Belong[u]].push_back(Belong[v]);
                }
            }
            if(hungary()) puts("Yes");
            else puts("No");
        }
        return 0;
    }
  • 相关阅读:
    [HDU6793] Tokitsukaze and Colorful Tree
    [NOI2020]命运
    [NOI2020]美食家
    模拟9
    晚测2
    模拟8
    联考4
    模拟7
    模拟6
    关于数论
  • 原文地址:https://www.cnblogs.com/mfys/p/7260813.html
Copyright © 2020-2023  润新知