zoukankan      html  css  js  c++  java
  • 模拟比赛 树套环问题

    Problem I

    Time Limit : 3000/1500ms (Java/Other)   Memory Limit : 131072/131072K (Java/Other)
    Total Submission(s) : 28   Accepted Submission(s) : 7

    Font: Times New Roman | Verdana | Georgia

    Font Size:

    Problem Description

    A group is made of n people who are numbered from 0 to n1. Now they are requested to complete a project, and there should be only one member working on every stage while others take rest. For number i, if he is working on the first stage, he would transfer the next stage to (i+Ai)% n or (iAi)% n after finishing this stage. If the previous stage was worked by someone whose number is even number, he would transfer the next stage to number (i+Ai)% n after finishing this stage, if the previous stage is completed by someone whose number is odd number, he would transfer the next stage to number (iAi+n)% n after finishing this stage.

      Now ask who will work on only one stage at most.(No matter how long the work lasts, no matter who works on the first stage and no matter the first worker handover the next stage to (i+Ai)% n or (iAi)% n, they will work on only one stage at most)

    Input

    Output

    For each case, output two lines.

    First line contains a number indicates the quantity of members who satisfy the request.

    Next line output the number of each member who satisfy the request by order.

    If no one satisfy the request, the second line is blank.

    Sample Input

    2
    5
    1 2 3 1 2
    10
    2 0 7 1 -9 6 -4 -8 -3 8 
    

    Sample Output

    1
    0
    6
    0 2 5 6 7 8
    

    这题树套环太不容易了 至少连续写了一天

    首先一开始对于找环的处理 需要将每次不同点的dfs进行不同vis标记

    其次进行逆序dfs找重点的时候只需要判断已开始是不是环就可以了 之后不会有环的

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<map>
    #include<ctime>
    using namespace std;
    const int MAXN = 1e5 + 5;
    
    int n;
    int A[MAXN];
    int Next[MAXN<<1];
    int vis[MAXN<<1]; //dfs判环  之后用于判重
    int mean[MAXN<<1];
    int indegree[MAXN<<1];
    int no[MAXN];
    int go[MAXN];
    map<int,int> Hash;
    int target; // dfs时候编号用
    
    int cnt[MAXN<<1];
    int tot;
    vector<int> cc[MAXN];
    
    vector<int> mp[MAXN<<1];
    vector<int> ans;
    
    
    void Findloop(int x,int root){
    	if(x == root) return;
    	mean[x] = target;
    	cc[tot].push_back(x);
    	Findloop(Next[x], root);
    }
    void dfs(int x,int tag){
    //	printf("%d %d
    ",x,tag);
    	if(vis[x] != tag && vis[x]!=-1) return;
    
    	if(vis[x] == tag){
    		target = x;  mean[x] = target; Hash[target] = ++tot; cc[tot].clear();
    		cc[tot].push_back(x);
    		Findloop(Next[x],x);
    		return;
    	}
    	vis[x] = tag;
    	dfs(Next[x],tag);
    }
    
    void Find(int x,int pre){
    	for(auto i : mp[x]){
    		if(i == pre) continue;
    		go[i/2] ++;
    		if(go[i/2] == 2) no[i/2] = 1;
    		Find(i,x);
    		go[i/2] --;
    	}
    }
    int main(){
    	int T;
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d",&n);
    		tot = 0;
    		memset(cnt,0,sizeof(cnt));
    		memset(vis,-1,sizeof(vis));
    		memset(no,0,sizeof(no));
    		memset(go,0,sizeof(go));
    		memset(indegree,0,sizeof(indegree));
    		ans.clear(); Hash.clear();
    
    		for(int i = 0; i < n; ++i){
    			scanf("%d",&A[i]);
    		}
    		for(int i = 0; i < 2*n; ++i) { mean[i] = i; mp[i].clear(); }
    		for(int i = 0; i < n; ++i){
    			int t1,t2;
    			if(i%2==0) t1 = (i+A[i]+n)%n*2 , t2 = (i-A[i]+n)%n*2;
    			else       t1 = (i+A[i]+n)%n*2+1 , t2 = (i-A[i]+n)%n*2+1;
    			Next[2*i] = t1; Next[2*i+1] = t2;
    		}
    
    		for(int i = 0; i < n; ++i){
    			target = -1; dfs(2*i,2*i);
    			target = -1; dfs(2*i+1,2*i+1);
    		}
    	//	for(int i = 0 ; i < 2*n; ++i) printf("%d ",mean[i]); printf("
    ");
    
    		for(int i = 0; i < n; ++i){
    			int a = mean[2*i]; int b = mean[2*i+1]; int c = mean[Next[2*i]]; int d = mean[Next[2*i+1]];
    			if(a != c) mp[c].push_back(a), indegree[a] ++; 
    			if(d != b) mp[d].push_back(b),indegree[b] ++;
    		}memset(vis,0,sizeof(vis));
    
    		for(int i = 0; i < 2*n; ++i){
    			int tt = mean[i];
    			if(indegree[tt] == 0 && vis[tt] == 0){
    				if(Hash[tt]) {
    					for(auto j : cc[ Hash[tt] ]){
    						vis[j]++; no[j/2] = 1;
    					}
    				}else vis[tt]++, go[tt/2] ++;
    				Find(tt,-1);
    			}
    		}
    		
    		for(int i = 0; i < n; ++i) if(no[i] == 0) ans.push_back(i);
    		printf("%lu
    ",ans.size());
    		for(int i = 0; i < ans.size(); ++i)
    			if(!i) printf("%d",ans[i]);
    			else printf(" %d",ans[i]);
    		printf("
    ");
    	}
    	return 0;
    }
    
    


  • 相关阅读:
    基于node.js+socket.io+html5实现的斗地主游戏(1)概述
    [javascript]switchTab:仿腾讯首页Tab栏切换js插件
    [js]利用闭包向post回调函数传参数
    [CSS]利用伪元素实现一些特殊图形 from baidu校招
    [javascript]模块化&命名污染—from 编程精解
    [随手记]2014前端面试题解
    [IE bug] ajax请求 304解决方案
    [java]基于UDP的Socket通信Demo
    [JQuery]ScrollMe滚动特效插件
    java.lang.OutOfMemoryError及解决方案
  • 原文地址:https://www.cnblogs.com/Basasuya/p/8433769.html
Copyright © 2011-2022 走看看