列表

详情


NC51311. Going from u to v or from v to u?

描述

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?

输入描述

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 , 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.

输出描述

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

示例1

输入:

1
3 3
1 2
2 3
3 1

输出:

Yes

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

Java(javac 1.8) 解法, 执行用时: 90ms, 内存消耗: 18808K, 提交时间: 2021-03-16 17:19:53

import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;

public class Main {

    static class Task {

        public static String roundS(double result, int scale){
            String fmt = String.format("%%.%df", scale);
            return String.format(fmt, result);
//        DecimalFormat df = new DecimalFormat("0.000000");
//        double result = Double.parseDouble(df.format(result));
        }


        // 有向图的强连通分量,非递归

        void tarjanStack(int u) {

            int stk[] = new int[100001];
            int p  =1; stk[0] = u;
            ot:while(p>0) {
                u  = stk[p-1];
                if (dfn[u] == 0) {
                    low[u] = dfn[u] = ++time;
                    stack[top++] = u;
                }
                // remember h will be changed after using it
                for (; h[u] != -1; h[u] = ne[h[u]]) {
                    int v = to[h[u]];
                    if (dfn[v] == 0) {
                        stk[p++] = v;
                        continue ot;
                        //  low[u] = Math.min(low[u], low[v]);
                    } else if (sccno[v] == 0) {
                        // dfn>0 but sccno==0, means it's in current stack
                        low[u] = Math.min(low[u], low[v]);
                    }
                }
                p--;
                if (dfn[u] == low[u]) {
                    sccno[u] = ++scc_cnt;
                    cnt[scc_cnt]++;
                    while (stack[top - 1] != u) {
                        sccno[stack[top - 1]] = scc_cnt;
                        --top;
                        cnt[scc_cnt]++;
                    }
                    --top;
                }
                if(p>=1){
                    int fa = stk[p-1];
                    low[fa] = Math.min(low[fa], low[u]);
                }
            }
        }
        int[] h,ne,to;
        int dfn[],low[],stack[],cnt[];
        int sccno[];

        boolean iscut[];
        int time = 0,top = 0;
        int scc_cnt;int ct = 0;
        int root = 0;
        void add(int u,int v){
            to[ct] = v;
            ne[ct] = h[u];
            h[u] = ct++;
        }



        int[] h1,to1,ne1;
        int ct1 = 0;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
           int t=  in.nextInt();
           while(t-->0) {
               int n = in.nextInt();
               int m = in.nextInt();

               ct = 0;
               scc_cnt = 0;
               h = new int[n + 1];
               Arrays.fill(h, -1);
               h1 = new int[n + 1];
               Arrays.fill(h1, -1);

               {
                   ne = new int[m];
                   to = new int[m];
                   to1 = new int[m];
                   ne1 = new int[m];
               }


               {
                   dfn = new int[n + 1];
                   low = new int[n + 1];
                   stack = new int[n + 1];
                   sccno = new int[n + 1];
                   cnt = new int[n + 1];
               }

               for (int j = 0; j < m; ++j) {
                   int u = in.nextInt();
                   int v = in.nextInt();
                   add(u, v);
               }
               int hh[] = h.clone();

               for (int i = 1; i <= n; i++) {
                   if (dfn[i] == 0) tarjanStack(i);
               }


               int du[] = new int[scc_cnt + 1];
               h1 = new int[scc_cnt + 1];
               Arrays.fill(h1, -1);
               to1 = new int[m];
               ne1 = new int[m];
               // scc_cnt 个点


               h = hh;
               ct1 = 0;
               for (int i = 1; i <= n; i++) {
                   for (int j = h[i]; j != -1; j = ne[j]) {
                       int y = to[j];
                       if (sccno[i] != sccno[y]) {
                           // add(sccno[i],sccno[y]);  // 建新图
                           to1[ct1] = sccno[y];
                           ne1[ct1] = h1[sccno[i]];
                           h1[sccno[i]] = ct1++;
                           du[sccno[y]]++; //存入度
                       }
                   }
               }


               int q[] = new int[scc_cnt + 1];
               int end = 0;
               int st = 0;
               int dp[] = new int[scc_cnt + 1];

               long k = 0;
               long ans = 0;
               for (int i = 1; i <= scc_cnt; ++i) {
                   if (du[i] == 0) {
                       q[end++] = i;
                       dp[i] = 1;
                       break;
                   }
               }


               while (st < end) {
                   int cur = q[st++];

                   for (int i = h1[cur]; i != -1; i = ne1[i]) {
                       int y = to1[i];
                       dp[y] = 1;

                       if (--du[y] == 0) {
                           q[end++] = y;
                       }
                       break;
                   }
               }
                boolean ok = true;
               for (int i = 1; i <= scc_cnt; ++i) {
                   if (dp[i] == 0) {
                       ok  = false;
                   }
               }

               out.println(ok?"Yes":"No");

           }





        }


//        int t = in.nextInt();
//        int n = in.nextInt();
//        int m = in.nextInt();
//
//        ct = 0;
//        h = new int[n];Arrays.fill(h,-1);
//        if(t==1) {
//            to = new int[m * 2];
//            ne = new int[m * 2];
//
//            fob = new boolean[m * 2];
//        }else{
//            to = new int[m];
//            ne = new int[m];
//
//        }
//
//
//        int rd[] = new int[n];
//        int cd[] = new int[n];
//        li = new int[m];
//        tp = m-1;
//
//        int rt=  0;
//
//        for(int i=0;i<m;++i){
//            int u = in.nextInt()-1;
//            int v = in.nextInt()-1;
//            add(u,v);
//            if(t==1){
//                add(v,u);
//            }
//            cd[u]++;
//            rd[v]++;
//            rt = u;
//        }
//
//        if(t==2){
//
//            for(int i=0;i<n;++i){
//                if(rd[i]!=cd[i]){
//                    out.println("NO");return;
//                }
//            }
//        }else{
//
//            for(int i=0;i<n;++i){
//                if(((rd[i]+cd[i])%2)>0){
//                    out.println("NO");return;
//                }
//            }
//
//        }
//
//
//
//        dfs11(rt, t);
//
//
//
//        if(tp!=-1){
//            out.print("NO");
//            return;
//        }
//
//        out.println("YES");
//
//        for(int i=0;i<m;++i){
//            out.print(li[i]+ " ");
//        }




















//            int f1[][] = new int[q][3];
//
//            for(int i=0;i<q;++i){
//                for(int j=0;j<3;++j){
//                    f1[i][j] = in.nextInt();
//                }
//            }
//
//
//                int h[] = new int[n+1];
//
//                Arrays.fill(h,-1);
//
//
//                int ne[] = new int[p*2+q];
//                int to[] = new int[p*2+q];
//                int wt[] = new int[p*2+q];
//                ct = 0;
//            Func fk = (int x,int y,int z) -> {
//                to[ct] = y;
//                ne[ct] = h[x];
//                wt[ct] = z;
//                h[x] = ct++;
//            };
//
//                for(int i=0;i<p;++i){
//                    int u =  f[i][0];
//                    int v =  f[i][1];
//
//
//
//
//                        fk.add(u,v,f[i][2]);
//                        fk.add(v,u,f[i][2]);
//                }
//
//            for(int i=0;i<q;++i){
//                int u =  f1[i][0];
//                int v =  f1[i][1];
//
//
//
//
//                fk.add(u,v,f1[i][2]);
//            }




//                int dp[] = new int[n+1];
//                Arrays.fill(dp,100000000);
//                dp[s] = 0;
//
//
//                PriorityQueue<int[]> qu = new PriorityQueue<>(Comparator.comparingInt((x)->x[0]));
//                qu.add(new int[]{0,s});
//                while(qu.size()>0){
//                    int cc[] = qu.poll();
//                    int cur =  cc[1];
//                    if(cc[0]!=dp[cur]) continue;
//                    for(int j = h[cur];j!=-1;j=ne[j]){
//                        int v = to[j];
//                        if(dp[v] > dp[cur] + wt[j]){
//                            dp[v] = dp[cur] + wt[j];
//                            qu.offer(new int[]{dp[v],v});
//                        }
//                    }
//                }
//
//                for(int j=1;j<=n;++j){
//                    if(dp[j]==100000000){
//                        out.println("NO PATH");
//                    }else{
//                        out.println(dp[j]);
//                    }
//                }



//                for(int t=0;t<5;++t) {
//                    int at = fi[t];
//                    dp[at][t] = 0;
//                    PriorityQueue<int[]> q = new PriorityQueue<>(Comparator.comparingInt((x) -> x[0]));
//                    q.offer(new int[]{0, at});
//                    while (q.size() > 0) {
//                        int cur[] = q.poll();
//                        if (cur[0] != dp[cur[1]][t]) continue;
//                        int i = cur[1];
//                        for (int j = h[i]; j != -1; j = ne[j]) {
//                            int v = to[j];
//                            if (dp[i][t] + wt[j] < dp[v][t]) {
//                                dp[v][t] = dp[i][t] + wt[j];
//                                q.offer(new int[]{dp[v][t], v});
//                            }
//                        }
//                    }
//                }
//                int cl[] = new int[]{0,1,2,3,4};
//                int rs = Integer.MAX_VALUE;
//                do{
//                    int s= dp[1][cl[0]];
//                    for(int j=0;j<4;++j){
//                        int nxt = fi[cl[j+1]];
//                        s += dp[nxt][cl[j]];
//                    }
//                    rs = Math.min(rs,s);
//
//
//                }while(next_perm(cl));
//
//                out.print(rs);










        boolean next_perm(int[] a){
            int len = a.length;
            for(int i=len-2,j = 0;i>=0;--i){
                if(a[i]<a[i+1]){
                    j = len-1;
                    for(;a[j]<=a[i];--j);
                    int p = a[j];
                    a[j] = a[i];
                    a[i] = p;
                    j = i+1;
                    for(int ed = len-1;j<ed;--ed) {
                        p = a[ed];
                        a[ed] = a[j];
                        a[j++] = p;
                    }
                    return true;
                }
            }
            return false;
        }


        static long mul(long a, long b, long p) {
            long res = 0, base = a;

            while (b > 0) {
                if ((b & 1L) > 0)
                    res = (res + base) % p;

                base = (base + base) % p;
                b >>= 1;
            }

            return res;
        }

        static long mod_pow(long k, long n, long p) {
            long res = 1L;
            long temp = k % p;

            while (n != 0L) {
                if ((n & 1L) == 1L) {
                    res = mul(res, temp, p);
                }

                temp = mul(temp, temp, p);
                n = n >> 1L;
            }

            return res % p;
        }


        public static double roundD(double result, int scale) {
            BigDecimal bg = new BigDecimal(result).setScale(scale, RoundingMode.UP);
            return bg.doubleValue();
        }



    }
    private static void solve() {
        InputStream inputStream = System.in;
//                InputStream inputStream  = null;
//                try {
//                    inputStream = new FileInputStream(new File("D:\\chrome_download\\exp.out"));
//                } catch (FileNotFoundException e) {
//                    e.printStackTrace();
//                }
        OutputStream outputStream = System.out;
//                OutputStream outputStream = null;
//                File f = new File("D:\\chrome_download\\");
//                try {
//                    f.createNewFile();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//                try {
//                    outputStream = new FileOutputStream(f);
//                } catch (FileNotFoundException e) {
//                    e.printStackTrace();
//                }
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Task task = new Task();
        task.solve(1, in, out);
        out.close();
    }
    public static void main(String[] args) {
        // new Thread(null, () -> solve(), "1", (1 << 30)).start();
        solve();
    }
    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }
        public String nextLine() {
            String line = null;

            try {
                line = reader.readLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            return line;
        }
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }
        public char nextChar() {
            return next().charAt(0);
        }
        public int[] nextArray(int n) {
            int res[] = new int[n];

            for (int i = 0; i < n; ++i) {
                res[i] = nextInt();
            }

            return res;
        }

        public long nextLong() {
            return Long.parseLong(next());
        }
        public double nextDouble() {
            return Double.parseDouble(next());
        }
    }
}

C++(g++ 7.5.0) 解法, 执行用时: 12ms, 内存消耗: 5292K, 提交时间: 2022-08-21 22:04:30

#include <vector>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std ;
  
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
#define siz(a) (int) a.size()
#define pb push_back
#define mp make_pair
#define ll long long
#define fi first
#define se second
  
const int N = 100010 ;
  
int n, m, ans1, ans2, ans3, tot, scc ;
vector <int> e[N] ;
int dfn[N], low[N], ins[N], bl[N], in[N], out[N] ;
stack <int> s ;
  
void clear() {
    tot = 0, ans1 = 0, ans2 = 0, ans3 = 0, scc = 0 ;
    memset(dfn, 0, sizeof(dfn)) ;
    memset(low, 0, sizeof(low)) ;
    memset(ins, 0, sizeof(ins)) ;
    memset(bl, 0, sizeof(bl)) ;
    memset(in, 0, sizeof(in)) ;
    memset(out, 0, sizeof(out)) ;
    rep(i, 1, n) e[i].clear() ;
}
  
  
void tarjan(int u) {
    dfn[u] = low[u] = ++tot ;
    ins[u] = 1 ; s.push(u) ;
    rep(i, 0, siz(e[u]) - 1) {
        int v = e[u][i] ;
        if (!dfn[v]) {
            tarjan(v) ;
            low[u] = min(low[u], low[v]) ;
        }
        else if (ins[v]) low[u] = min(low[u], dfn[v]) ;
    }
    if (low[u] == dfn[u]) {
        bl[u] = ++scc ;
        ins[u] = 0 ;
        while (s.top() != u) {
            int v = s.top() ;
            ins[v] = 0 ;
            bl[v] = scc ;
            s.pop() ;
        }
        s.pop() ;
    }
}
  
signed main() {
    int t ; scanf("%d", &t) ;
    while (t--) {
        clear() ;
        scanf("%d%d", &n, &m) ;
        rep(i, 1, m) {
            int a, b ; scanf("%d%d", &a, &b) ;
            e[a].pb(b) ;
        }
        rep(i, 1, n) if (!dfn[i]) tarjan(i) ;
        rep(u, 1, n)
        rep(j, 0, siz(e[u]) - 1) {
            int U = bl[u], V = bl[e[u][j]] ;
            if (U != V) in[V]++, out[U]++ ;
        }
        rep(i, 1, scc) {
            if (in[i] == 0 && out[i] >= 1) ans1++ ;
            if (in[i] >= 1 && out[i] == 0) ans2++ ;
            if (in[i] >= 1 && out[i] >= 1) ans3++ ;
        }
        if (scc == 1 || (ans1 == 1 && ans2 == 1 && ans1 + ans2 + ans3 == scc)) puts("Yes") ;
        else puts("No") ;
    }
    return 0 ;
}

C++11(clang++ 3.9) 解法, 执行用时: 9ms, 内存消耗: 5244K, 提交时间: 2020-10-14 11:59:27

#include<stack>
#include<vector>
#include<queue>
#include<cstdio>
#include<cstring>
#define ui unsigned int
using namespace std;
const int M=100500;
int dfn[M],vis[M],fa[M],low[M];
int ind,ti,in[M];
int n,m;
vector<int>v[M];
vector<int>G[M];
stack<int>s;
void tarjan(int x)
{
	low[x]=dfn[x]=++ind;vis[x]=1;s.push(x);
	for(ui i=0;i<v[x].size();i++)
	{
		int go=v[x][i];
		if(!dfn[go])
		{
			tarjan(go);
			low[x]=min(low[x],low[go]);
		}
		else if(vis[go])
			low[x]=min(low[x],dfn[go]);
	}
	if(low[x]==dfn[x])
	{
		int t=-1;ti++;
		while(t!=x)
		{
			t=s.top();s.pop();
			vis[t]=0;fa[t]=ti;
		}
	}
	return ;
}
int top()
{
	queue<int>q;int cnt=0;
	for(int i=1;i<=ti;i++)
		if(!in[i])q.push(i);
	if(q.size()>1)return 0;
	while(q.size())
	{
		int u=q.front();q.pop();cnt++;
		for(ui i=0;i<G[u].size();i++)
		{
			int go=G[u][i];
			in[go]--;
			if(!in[go])q.push(go);
		}
		if(q.size()>1)return 0;
	}
	if(cnt!=ti)return 0;
	return 1;
}
void clean()
{
	ti=ind=0;
	for(int i=1;i<=n;i++)
	v[i].clear(),G[i].clear(),
		in[i]=dfn[i]=low[i]=vis[i]=fa[i]=0;
}
int main()
{
	int t,a,b;
	for(scanf("%d",&t);t--;)
	{
		scanf("%d%d",&n,&m);clean();
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d",&a,&b);
			v[a].push_back(b);
		}
		for(int i=1;i<=n;i++)
			if(!dfn[i])tarjan(i);
		for(int i=1;i<=n;i++)
		for(ui k=0;k<v[i].size();k++)
		{
			int go=v[i][k];
			if(fa[i]!=fa[go])
				G[fa[i]].push_back(fa[go]),in[fa[go]]++;
		}
		if(top())puts("Yes");
		else puts("No");
	}
}

上一题