zoukankan      html  css  js  c++  java
  • The 2014 ACM-ICPC Asia Mudanjiang Regional First Round C ZOj 3811

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5343

    比赛时候, 用BFS, 一直MLE, 坑爹啊;

    题意: 保安巡逻仓库, 老板在耨写仓库上装了传感器, 传感器只能记录一次, 所以只能记录第一次经过这个仓库;但是保安可能会FQ, 黑魔法等非正常走路方式

    给N个仓库, M条路, K个传感器, 接着输入k个传感器的位置, 接着M条路, 接着一个L, 代表L个传感器工作了, 下面输入传感器依次工作的顺序;

    如果保安正常走路了, 并且有可能走边了所有仓库就输出Yes;

    第一次用BFS, MLE,

    后来用DFS, 直接查, TLE

    Code

    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    #include <string>
    #include <vector>
    #include <queue>
    using namespace std;
    #define N 100005
    
    vector<int> v[N];
    int  par[N], sensor[N], order[N], n, m, k, l, flag;
    int find(int x)
    {
    	int y = x;
    	while(y != par[y])
    	{
    		y = par[y];
    	}
    	while(x != par[x])
    	{
    		int px = par[x];
    		par[x] = y;
    		x = px;
    	}
    	return y;
    }
    void unite(int x, int y)
    {
    	x = find(x);
    	y = find(y);
    	par[x] = y;
    }
    void dfs(int y)
    {
    	for(int i=0; i<(int)v[y].size(); i++)
    	{
    		if(!sensor[v[y][i]])
    		{
    			if(find(v[y][i] != find(y)))
    			{
    				//printf("#%d %d
    ", y, v[y][i]);
    				unite(v[y][i], y);
    			}
    		}
    	}
    }
    bool judge(int x, int y)
    {
    	int i;
    	for(i=0;i<(int)v[x].size();i++)
    	{
    		if(v[x][i] == y) return 0;
    	}
    	return 1;
    }
    int  main()
    {
    	int t;
    	scanf("%d", &t);
    	while(t--)
    	{
    		int i,  k, x, y;
    		memset(sensor, 0, sizeof(sensor));
    		memset(order, 0, sizeof(order));
    		scanf("%d %d %d", &n, &m, &k);
    		for(i=0;i<=n; i++)
    		{
    			par[i] = i;
    			v[i].clear();
    		}
    		for(i=0;i<k;i++)
    		{
    			scanf("%d", &x);
    			sensor[x] = 1;
    		}
    		for(i=0;i<m;i++)
    		{
    			scanf("%d %d", &x, &y);
    			if(!judge(x, y)) continue;
    			v[x].push_back(y);
    			v[y].push_back(x);
    		}
    		scanf("%d", &l);
    		for(i=0;i<l;i++)
    		{
    			scanf("%d", &order[i]);
    		}
    		flag = 1;
    		dfs(order[0]);
    		sensor[order[0]] = 0;
    		for(i=1;i<l;i++)
    		{
    			dfs(order[i]);
    			sensor[order[i]] = 0;
    			if(find(order[i]) != find(order[i-1]))
    			{
    				flag = 0;
    				break;
    			}
    		}
    
    		if(flag) printf("YES
    ");
    		else printf("NO
    ");
    	}
    	return 0;
    }
    


    后来百度了题解

    看到了一同学是一个一个点的拓展成一个区域,序列中下个点如果拓展的点和这个区域有重合的那么就说明有一条路径

    细节问题:l<k 一定是NO,图不连通的话一定是NO。

    Code

    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    #include <string>
    #include <vector>
    #include <queue>
    using namespace std;
    #define N 100010
    
    vector<int> v[N];
    int  par[N], sensor[N], order[N], n, m, k, l, flag;
    int find(int x)
    {
    	int y = x;
    	while(y != par[y])
    	{
    		y = par[y];
    	}
    	while(x != par[x])
    	{
    		int px = par[x];
    		par[x] = y;
    		x = px;
    	}
    	return y;
    }
    bool unite(int u, int v)
    {
    	int fa1 = find(u);
    	int fa2 = find(v);
    	par[fa2] = fa1;
    	return fa1 == fa2;
    }
    void dfs(int y)
    {
    	for(int i=0; i<(int)v[y].size(); i++)
    	{
    		if(!sensor[v[y][i]])
    		{
    			if(!unite(v[y][i], y))
    			{
    				dfs( v[y][i] );
    			}
    		}
    	}
    }
    int  main()
    {
    	int t;
    	scanf("%d", &t);
    	while(t--)
    	{
    		int i, x, y;
    		memset(sensor, 0, sizeof(sensor));
    
    		scanf("%d %d %d", &n, &m, &k);
    		for(i=0;i<=n; i++)
    		{
    			par[i] = i;
    			v[i].clear();
    		}
    		for(i=0;i<k;i++)
    		{
    			scanf("%d", &x);
    			sensor[x] = 1;
    		}
    		for(i=0;i<m;i++)
    		{
    			scanf("%d %d", &x, &y);
    			v[x].push_back(y);
    			v[y].push_back(x);
    		}
    		scanf("%d", &l);
    		for(i=0;i<l;i++)
    		{
    			scanf("%d", &order[i]);
    		}
    		if (l < k)
    		{
    			printf("No
    ");
    			continue;
    		}
    
    		flag = 1;
    		dfs(order[0]);
    		sensor[order[0]] = 0;
    		for(i=1;i<l;i++)
    		{
    			dfs(order[i]);
    			sensor[order[i]] = 0;
    			if(find(order[i]) != find(order[i-1]))
    			{
    				flag = 0;
    				break;
    			}
    		}
    		for(i=2;i<=n;i++)
    		{
    			if(find(i) != find(1))
    			{
    				flag = 0;
    				break;
    			}
    		}
    		if(flag) printf("Yes
    ");
    		else printf("No
    ");	
    	}
    	return 0;
    }
    

    直接BFS,

    解题思路:首先判断是否为联通图,不连通的话肯定到不了。其次判断l是否等于k,如果不等于的话,说明至少有一个仓库到不了,剩下的就是考虑进过仓库的顺序,因为起点不限,所以第一个仓库的位置不会有问题,以第一个仓库为起点,做BFS,碰到有传感器的仓库将传感器关闭,并且将节点标记为1,表示说下一个位置可以直接到达该位置。然后考虑第二个位置,如果第二位置上的传感器没有关闭,则说明由第一个仓库到不了第二个仓库,否则重复操作,以第二个仓库为起点,做BFS

    来自http://blog.csdn.net/keshuai19940722/article/details/39136453

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    const int maxn = 100005;
    
    bool flag;
    int N, M, C, t[maxn], v[maxn], f[maxn];
    vector<int> g[maxn];
    
    inline int getfar(int x) {
        return x == f[x] ? x : f[x] = getfar(f[x]);
    }
    
    void init () {
        scanf("%d%d%d", &N, &M, &C);
        int x, a, b, n = N;
    
        memset(t, 0, sizeof(t));
        memset(v, 0, sizeof(v));
        for (int i = 0; i <= N; i++) {
            f[i] = i;
            g[i].clear();
        }
    
        for (int i = 0; i < C; i++) {
            scanf("%d", &x);
            t[x] = 1;
        }
    
        for (int i = 0; i < M; i++) {
            scanf("%d%d", &a, &b);
    
            g[a].push_back(b);
            g[b].push_back(a);
    
            int p = getfar(a), q = getfar(b);
            if (p != q) {
                f[p] = q;
                n--;
            }
        }
    
        flag = (n == 1);
    }
    
    void bfs(int s) {
        queue<int> que;
        t[s] = 0; v[s] = 1;
        que.push(s);
    
        while (!que.empty()) {
            int u = que.front();
            que.pop();
    
            for (int i = 0; i < g[u].size(); i++) {
                int k = g[u][i];
    
                if (v[k] || t[k]) {
                    v[k] = 1;
                    t[k] = 0;
                    continue;
                }
    
                v[k] = 1;
                que.push(k);
            }
        }
    }
    
    bool judge () {
        int n, x;
        scanf("%d", &n);
    
        if (n < C)
            flag = false;
    
        for (int i = 0; i < n; i++) {
            scanf("%d", &x);
            if (flag == false || (t[x] && i)) {
                flag = false;
                continue;
            }
            bfs(x);
        }
        return flag;
    }
    
    int main () {
        int cas;
        scanf("%d", &cas);
        while (cas--) {
            init();
            printf("%s
    ", judge() ? "Yes" : "No");
        }
        return 0;
    }




    www.cnblogs.com/tenlee
  • 相关阅读:
    Java泛型学习笔记
    Java泛型学习笔记
    Java泛型学习笔记
    Java泛型学习笔记
    Java泛型学习笔记
    Java泛型学习笔记
    Java泛型学习笔记
    有1到100共100个数, 从1开始, 每隔1, 2, 3... 个数拿走一个数, 最后剩下几?(约瑟夫环)
    推荐一个自动抽取pdf高亮笔记的web应用
    协程
  • 原文地址:https://www.cnblogs.com/tenlee/p/4420128.html
Copyright © 2011-2022 走看看