zoukankan      html  css  js  c++  java
  • [codeforces1270G]Subset with Zero Sum 数学 建图

    题目:

    Time limit2000 ms

    Memory limit262144 kB

    You are given nn integers a1,a2,,ana1,a2,…,an, such that for each 1in1≤i≤n holds inaii1i−n≤ai≤i−1.

    Find some nonempty subset of these integers, whose sum is equal to 00. It can be shown that such a subset exists under given constraints. If there are several possible subsets with zero-sum, you can find any of them.

    Input

    Each test contains multiple test cases. The first line contains the number of test cases tt (1t1061≤t≤106). The description of the test cases follows.

    The first line of each test case contains a single integer nn (1n1061≤n≤106).

    The second line of each test case contains nn integers a1,a2,,ana1,a2,…,an (inaii1i−n≤ai≤i−1).

    It is guaranteed that the sum of nn over all test cases does not exceed 106106.

    Output

    For each test case, output two lines.

    In the first line, output ss (1sn1≤s≤n) — the number of elements in your subset.

    In the second line, output ss integers i1,i2,,isi1,i2,…,is (1ikn1≤ik≤n). All integers have to be pairwise different, and ai1+ai2++aisai1+ai2+⋯+ais has to be equal to 00. If there are several possible subsets with zero-sum, you can find any of them.

    Example

    Input
    2
    5
    0 1 2 3 4
    4
    -3 1 1 1
    
    Output
    1
    1 
    4
    1 4 3 2 

    【题意】
    一序列数a1,a2,…,an,满足 i−n≤ai≤i−1 (1≤i≤n)
    求这个序列的一个子集,使子集的和为0

    【思路】
    i−n≤ai≤i−1
    ∴ 1<=i-ai<=n
    构建一个图,对每个ai​,建一条从 i 到 i−ai 的边,由于每个点都有出度,整个图必定有环。
    找到这个环,环上的ai之和为0.
    example:
    1-a1=2
    2-a2=3
    3-a3=1
    把3个等式加起来得a1+a2+a3=0;
    建边:1指向2,2指向3,3指向1

    【坑】

    不要忘记初始化
    每个点都有一个出边,而且指向1~n内,所以找到一个环就可以停下了(首尾相接)
    t的范围是(1~1e6)如果每次初始化都用memset,就是O(n)的,就T掉了,所以初始化要用for循环

    找环直接判断首位相接,不要用tarjan
    初始化不要用memset!

     1 #include<iostream>
     2 #include<vector>
     3 #include<stack>
     4 #include<cstring>
     5 using namespace std;
     6 int const maxn=1e6+7;
     7 int a[maxn],ans[maxn],n,to[maxn],sum,pos;
     8 bool vis[maxn];
     9 stack<int>sta;
    10 inline int get_num(){
    11     char ch=getchar();
    12     bool flag=false;
    13     int num=0;
    14     while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
    15     while(ch>='0'&&ch<='9'){num=(num<<1)+(num<<3)+ch-'0';ch=getchar();}
    16     if(flag)return -1*num;
    17     else return num;
    18 }
    19 void init(){
    20     for(int i=0;i<=n;i++)vis[i]=0;
    21     while(!sta.empty())sta.pop();
    22     sum=0;pos=0;
    23 }
    24 int main(){
    25     int t;
    26     scanf("%d",&t);
    27     while(t--){
    28         n=get_num();
    29         init();
    30         for(int i=1;i<=n;i++){
    31             a[i]=get_num();to[i]=i-a[i];
    32             if(a[i]==0)pos=i;
    33         }
    34         if(pos){printf("1
    %d
    ",pos);continue;}
    35         else{
    36             int p=1;
    37             while(!vis[p]){
    38                 sta.push(p);
    39                 vis[p]=true;
    40                 p=to[p];
    41             }
    42             while(sta.top()!=p){ans[++sum]=sta.top();sta.pop();}
    43             printf("%d
    ",sum+1);
    44             for(int i=1;i<=sum;i++)printf("%d ",ans[i]);
    45             printf("%d
    ",p);
    46         }
    47     }
    48     return 0;
    49 }/*
    50 题意:
    51 一序列数a1,a2,…,an,满足  i−n≤ai≤i−1  (1≤i≤n)
    52 求这个序列的一个子集,使子集的和为0
    53 
    54 思路
    55  i−n≤ai≤i−1
    56  ∴ 1<=i-ai<=n  
    57  构建一个图,对每个ai​,建一条从 i 到 i−ai 的边,由于每个点都有出度,整个图必定有环。
    58  找到这个环,环上的ai之和为0.
    59  example:
    60  1-a1=2
    61  2-a2=3
    62  3-a3=1
    63  把3个等式加起来得a1+a2+a3=0;
    64 建边:1指向2,2指向3,3指向1
    65 
    66 
    67 这个题的坑:
    68 不要忘记初始化
    69 每个点都有一个出边,而且指向1~n内,所以找到一个环就可以停下了(首尾相接)
    70 t的范围是(1~1e6)如果每次初始化都用memset,就是O(n)的,就T掉了,所以初始化要用for循环
    71 
    72 找环直接判断首位相接,不要用tarjan
    73 初始化不要用memset!
    74 */
  • 相关阅读:
    【餐厅】 What kind of food would you like to eat tonight?
    深入分析总线设备驱动模型的框架
    总线设备驱动模型
    Qt工程管理
    USB摄像头驱动框架分析
    浅析struct device结构体
    一、mysql下载与安装
    vsCode创建自己的代码模板
    vsCode多选多个元素进行统一修改
    博客园添加目录
  • 原文地址:https://www.cnblogs.com/conver/p/12188110.html
Copyright © 2011-2022 走看看