Ural 1042 Central Heating

Winter has come, but at the Ural State University heating is not turned on yet. There’s one little problem: the University is heated only if all of the valves are opened. There are some technicians at the University. Each of them is responsible for one or more valves. There may be several technicians responsible for the same valve. When a technician gets an instruction to turn on the heating he goes round all of his valves and turns them. It means that if a valve was opened then he closes it, and if it was closed then he opens it. It is well known that every technician earns his money not in vain so it’s impossible to replace any technician by any combination of other technicians.
Your task is to determine who of the technicians is to get an instruction “to turn on the heating” in order to heat all the Ural State University. Note that there are N technicians and N valves at the University ( 1N250 ).

Input

The first line of the input contains the number N . The next N lines contain lists of the valves in charge of each of the technicians. It means that the line number i+1 contains numbers of the valves that the i-th technician is responsible for. Each list of valves is followed by 1 .

Output

An output should contain a list of technicians’ numbers sorted in ascending order. If several lists are possible, you should send to an output the shortest one. If it’s impossible to turn on the heating at the University, you should write “No solution”.

Sample

input

4
1 2 -1
2 3 4 -1
2 -1
4 -1

output

1 2 3

题目大意

一共有 N 个技术员和N个阀门,技术员每人负责一个或多个阀门。当一个技术员接到指示后他就会把所有自己负责的阀门都转动一次。求哪些技术员应接到指示,从而使所有阀门都打开。

思路

高斯消元,把所有的减号换成异或。

代码

#include <cstdio>
#include <algorithm>

const int maxn=250;

int n,ans[maxn+1],tot;

struct matrix
{
  int a[maxn+1][maxn+2];

  inline int gauss()
  {
    for(register int i=1; i<n; ++i)
      {
        if(!a[i][i])
          {
            int j=i;
            while(j<=n)
              {
                if(a[j][i])
                  {
                    break;
                  }
                ++j;
              }
            if(j>n)
              {
                return 1;
              }
            for(register int k=i; k<=n+1; ++k)
              {
                std::swap(a[i][k],a[j][k]);
              }
          }
        for(register int j=i+1; j<=n; ++j)
          {
            if(a[j][i])
              {
                for(register int k=i; k<=n+1; ++k)
                  {
                    a[j][k]^=a[i][k];
                  }
              }
          }
      }
    for(register int i=n; i>1; --i)
      {
        for(register int j=1; j<i; ++j)
          {
            a[j][n+1]^=a[j][i]*a[i][n+1];
          }
      }
    return 0;
  }

  inline int print_ans()
  {
    for(register int i=1; i<=n; ++i)
      {
        if(a[i][n+1])
          {
            ++tot;
            ans[tot]=i;
          }
      }
    for(register int i=1; i<tot; ++i)
      {
        printf("%d ",ans[i]);
      }
    printf("%d",ans[tot]);
    return 0;
  }
};

matrix t;
int a;

int main()
{
  scanf("%d",&n);
  for(register int i=1; i<=n; ++i)
    {
      while(1)
        {
          scanf("%d",&a);
          if(a==-1)
            {
              break;
            }
          t.a[a][i]=1;
        }
    }
  for(register int i=1; i<=n; ++i)
    {
      t.a[i][n+1]=1;
    }
  if(t.gauss())
    {
      puts("No solution");
    }
  else
    {
      t.print_ans();
    }
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值