【Foreign】最大割 [线性基]

最大割

Time Limit: 15 Sec  Memory Limit: 256 MB

Description

  

Input

  

Output

  

Sample Input

  3 6
  1 2 1
  1 2 1
  3 3 111
  1 3 101101
  1 2 1011
  2 3 111011

Sample Output

  1
  0
  0
  101101
  101101
  110000

HINT

  l = log2(w)

  

Solution

  首先我们发现,由于XOR满足消去律,那么我们定义一个新点的点权为该点所有连边的XOR和,那么任意点XOR起来得到的值正是割的值,所以这样操作之后问题就转化为了:任取几个点,求XOR出的最大值,支持点权修改。

  那么我们现在显然得到了做法:线性基,并且我们需要维护一个可修改的线性基。

  线性基的加入方法:1.从大到小加入,如果这一位没有匹配元则加入当前值当作匹配元,退出;2.如果这一位有匹配元了就XOR完向后继续执行操作,若值=0则退出

  线性基的最值方法:用一个初值为0的Ans串,从大到小贪心,如果这一位有匹配元并且Ans串该位为0则XOR,继续向后

  线性基的维护方法:我们另外记录一个record表示这个基是由哪些值XOR出来的,比如我们要消去b,然后我们就用一个 有bXOR出来且主元最小 的基来消去其它含b的基中的b,其中主元定义为最高位的1,我们让最高位的1最小,这样往上消去的时候依然可以满足XOR出来可以满足线性基的条件性质。然后我们扫一遍,如果含有这个b则XOR一下,并且record要XOR那个基的record,这样才可以保证record的记录不漏

  这道题就是先删除,然后再加入,每次询问求最值即可。

Code

  1 #include<iostream>  
  2 #include<algorithm>  
  3 #include<cstdio>  
  4 #include<cstring>  
  5 #include<cstdlib>  
  6 #include<cmath>  
  7 #include<bitset>
  8 using namespace std;
  9 
 10 const int ONE = 2001;
 11 const int L = 1005;
 12 
 13 int T,n,x,y;
 14 int PD;
 15 char s[ONE];
 16 int Link[ONE];
 17 
 18 bitset <L> record[ONE],A[ONE];
 19 bitset <L> Ans,P;
 20  
 21 int get() 
 22 { 
 23         int res,Q=1;    char c;
 24         while( (c=getchar())<48 || c>57)
 25         if(c=='-')Q=-1;
 26         if(Q) res=c-48; 
 27         while((c=getchar())>=48 && c<=57) 
 28         res=res*10+c-48; 
 29         return res*Q; 
 30 }
 31 
 32 void Deal_first()
 33 {
 34         scanf("%s",s+1);
 35         int len = strlen(s+1);  
 36         P.reset();
 37         for(int i=1;i<=len;i++)
 38             P[L-len+i] = s[i]-'0';
 39 }
 40 
 41 void Add(int k)
 42 {
 43         for(int pos=1;pos<=L;pos++)
 44         if(A[k][pos])
 45         {
 46             if(!Link[pos])
 47             {
 48                 Link[pos] = k;
 49                 break;
 50             }
 51             else
 52             {
 53                 A[k] ^= A[Link[pos]];
 54                 record[k] ^= record[Link[pos]];
 55                 if(!A[k].any()) break;
 56             }
 57         }
 58 }
 59 
 60 void Update(int x)
 61 {
 62         int k=0;
 63         for(int i=1;i<=n;i++)
 64         if(record[i][x] && !A[i].any())
 65         {
 66             k=i;
 67             break;
 68         }
 69         
 70         if(!k)
 71         {
 72             for(int i=L;i>=1;i--)
 73             {
 74                 if(Link[i] && record[Link[i]][x])
 75                 {
 76                     k = Link[i];
 77                     Link[i] = 0;
 78                     break;
 79                 }
 80             }
 81         }
 82         
 83         for(int i=1;i<=n;i++)
 84         {
 85             if(i!=k && record[i][x])
 86             {
 87                 A[i] ^= A[k];
 88                 record[i] ^= record[k];
 89             }
 90         }
 91         
 92         A[k] ^= P; Add(k);
 93 }
 94 
 95 int main()
 96 {
 97         n=get();    T=get();
 98         for(int i=1;i<=n;i++) record[i][i] = 1;
 99         while(T--)
100         {
101             x=get();    y=get();
102             Deal_first();
103             Update(x);    Update(y);
104             
105             Ans.reset(); PD=0;
106             for(int i=1;i<=L;i++)
107             {
108                 if(Link[i] && !Ans[i]) Ans ^= A[Link[i]];
109                 if(Ans[i]) PD=1;
110                 if(PD) printf("%d",Ans[i]?1:0);
111             }
112             if(!PD) printf("0");
113             printf("\n");
114         }
115 }
View Code

 

posted @ 2017-03-03 21:31  BearChild  阅读(550)  评论(2编辑  收藏  举报