You are viewing a single comment's thread. Return to all comments →
In C:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define HASH_SIZE 1234555 typedef struct _node{ int t; int i; int c; int a; struct _node *next; } node; typedef struct _lnode{ int x; int w; struct _lnode *next; } lnode; int abss(int x); void insert_edge(int x,int y,int w); void dfs(int x,int c); void sort_a2(int*a,int*b,int size); void merge2(int*a,int*left_a,int*right_a,int*b,int*left_b,int*right_b,int left_size, int right_size); void sort_a_ad(int*a,int*c,int size,int*new_size); void merge_ad(int*a,int*left_a,int*right_a,int*c,int*left_c,int*right_c,int left_size, int right_size,int*new_size); void insert(int target,int idx,int c,int a); int search(int target,int idx,int *c); int solve(int target,int target2,int idx); void clean_table(); int N,w,b,ngs,*cans,*cdiff,*c,idx[200000],*trace,mark[200000]={0},diff[200000],f[200000],s[200000],*remain; lnode **table; node *hash[HASH_SIZE]={0}; int main(){ int M,x,y,gs,sum,ans,target,i,j,k; scanf("%d%d",&N,&M); table=(lnode**)malloc(N*sizeof(lnode*)); memset(table,0,N*sizeof(lnode*)); for(i=0;i<M;i++){ scanf("%d%d",&x,&y); insert_edge(x-1,y-1,1); } trace=(int*)malloc(N*sizeof(int)); memset(trace,0,N*sizeof(int)); for(i=gs=0;i<N;i++) if(!trace[i]){ w=b=0; dfs(i,0); x=i; if(table[i]) y=table[i]->x; else y=-1; if(w>b){ diff[gs]=w-b; f[gs]=x; s[gs]=y; } else{ diff[gs]=b-w; f[gs]=y; s[gs]=x; } idx[gs]=gs; gs++; } free(trace); clean_table(); free(table); cdiff=(int*)malloc(gs*sizeof(int)); c=(int*)malloc(gs*sizeof(int)); for(i=sum=0,ans=200001;i<gs;i++){ sum+=diff[i]; cdiff[i]=diff[i]; c[i]=1; } target=sum/2; sort_a2(diff,idx,gs); sort_a_ad(cdiff,c,gs,&ngs); remain=(int*)malloc(ngs*sizeof(int)); if(!M || ngs==1){ printf("%d %d\n",gs%2*cdiff[0],gs-1); for(i=0;i<gs-1;i++) printf("%d %d\n",f[i]+1,f[i+1]+1); return 0; } for(i=0;i<ngs;i++) if(i==0) remain[i]=c[i]*cdiff[i]; else remain[i]=remain[i-1]+c[i]*cdiff[i]; ans=solve(target,(sum+1)/2,ngs-1); cans=remain; memset(cans,0,ngs*sizeof(int)); for(i=ngs-1;i>=0;i--){ if(target<=0) break; if(i==0){ cans[i]=(target-1)/cdiff[i]+1; break; } search(target,i,&cans[i]); if(cans[i]==-1){ for(j=i;j>=0;j--) cans[j]=c[j]; break; } target-=cans[i]*cdiff[i]; } for(j=0,k=0;j<gs && k<ngs;k++){ x=j+cans[k]; for(;j<x;j++) mark[j]=1; while(diff[j]==cdiff[k] && j<gs) j++; } printf("%d %d\n",abss(2*ans-sum),gs-1); for(i=0;i<gs;i++) if(s[idx[i]]!=-1) k=i; for(i=0;i<gs;i++){ if(i==k) continue; if(mark[i]!=mark[k]) printf("%d %d\n",f[idx[i]]+1,f[idx[k]]+1); else printf("%d %d\n",f[idx[i]]+1,s[idx[k]]+1); } return 0; } int abss(int x){ return (x<0)?-x:x; } void insert_edge(int x,int y,int w){ lnode *t=malloc(sizeof(lnode)); t->x=y; t->w=w; t->next=table[x]; table[x]=t; t=malloc(sizeof(lnode)); t->x=x; t->w=w; t->next=table[y]; table[y]=t; return; } void dfs(int x,int c){ lnode *p; trace[x]=1; if(c) b++; else w++; for(p=table[x];p;p=p->next) if(!trace[p->x]) dfs(p->x,c^1); return; } void sort_a2(int*a,int*b,int size){ if (size < 2) return; int m = (size+1)/2,i; int*left_a,*left_b,*right_a,*right_b; left_a=(int*)malloc(m*sizeof(int)); right_a=(int*)malloc((size-m)*sizeof(int)); left_b=(int*)malloc(m*sizeof(int)); right_b=(int*)malloc((size-m)*sizeof(int)); for(i=0;i<m;i++){ left_a[i]=a[i]; left_b[i]=b[i]; } for(i=0;i<size-m;i++){ right_a[i]=a[i+m]; right_b[i]=b[i+m]; } sort_a2(left_a,left_b,m); sort_a2(right_a,right_b,size-m); merge2(a,left_a,right_a,b,left_b,right_b,m,size-m); free(left_a); free(right_a); free(left_b); free(right_b); return; } void merge2(int*a,int*left_a,int*right_a,int*b,int*left_b,int*right_b,int left_size, int right_size){ int i = 0, j = 0; while (i < left_size|| j < right_size) { if (i == left_size) { a[i+j] = right_a[j]; b[i+j] = right_b[j]; j++; } else if (j == right_size) { a[i+j] = left_a[i]; b[i+j] = left_b[i]; i++; } else if (left_a[i] <= right_a[j]) { a[i+j] = left_a[i]; b[i+j] = left_b[i]; i++; } else { a[i+j] = right_a[j]; b[i+j] = right_b[j]; j++; } } return; } void sort_a_ad(int*a,int*c,int size,int*new_size){ if (size < 2){ (*new_size)=size; return; } int m = (size+1)/2,i; int *left_a,*right_a,*left_c,*right_c; left_a=(int*)malloc(m*sizeof(int)); right_a=(int*)malloc((size-m)*sizeof(int)); left_c=(int*)malloc(m*sizeof(int)); right_c=(int*)malloc((size-m)*sizeof(int)); for(i=0;i<m;i++){ left_a[i]=a[i]; left_c[i]=c[i]; } for(i=0;i<size-m;i++){ right_a[i]=a[i+m]; right_c[i]=c[i+m]; } int new_l_size=0,new_r_size=0; sort_a_ad(left_a,left_c,m,&new_l_size); sort_a_ad(right_a,right_c,size-m,&new_r_size); merge_ad(a,left_a,right_a,c,left_c,right_c,new_l_size,new_r_size,new_size); free(left_a); free(right_a); free(left_c); free(right_c); return; } void merge_ad(int*a,int*left_a,int*right_a,int*c,int*left_c,int*right_c,int left_size, int right_size,int*new_size){ int i = 0, j = 0,index=0; while (i < left_size|| j < right_size) { if (i == left_size) { c[index] = right_c[j]; a[index++] = right_a[j]; j++; } else if (j == right_size) { c[index] = left_c[i]; a[index++] = left_a[i]; i++; } else if (left_a[i] <= right_a[j]) { c[index] = left_c[i]; a[index++] = left_a[i]; i++; } else { c[index] = right_c[j]; a[index++] = right_a[j]; j++; } if(index>1&&a[index-2]==a[index-1]){ c[index-2]+=c[index-1]; index--; } } (*new_size)=index; return; } void insert(int target,int idx,int c,int a){ int bucket=(target*200000LL+idx)%HASH_SIZE; node *t; t=(node*)malloc(sizeof(node)); t->t=target; t->i=idx; t->c=c; t->a=a; t->next=hash[bucket]; hash[bucket]=t; return; } int search(int target,int idx,int *c){ int bucket=(target*200000LL+idx)%HASH_SIZE; node *t=hash[bucket]; while(t){ if(t->t==target && t->i==idx){ *c=t->c; return t->a; } t=t->next; } return -1; } int solve(int target,int target2,int idx){ if(target<=0) return 0; if(target>remain[idx]) return -1; if(target==remain[idx]){ insert(target,idx,-1,target); return target; } int t,ans=200000,ansc,i; if(idx==0){ t=(target-1)/cdiff[idx]+1; return t*cdiff[idx]; } t=search(target,idx,&w); if(t!=-1) return t; for(i=0;i<=c[idx];i++){ t=solve(target-i*cdiff[idx],target2-i*cdiff[idx],idx-1); if(t!=-1){ if(t+i*cdiff[idx]<ans){ ans=t+i*cdiff[idx]; ansc=i; } if(t+i*cdiff[idx]==target || t+i*cdiff[idx]==target2){ insert(target,idx,i,t+i*cdiff[idx]); return t+i*cdiff[idx]; } } if(target-i*cdiff[idx]<=0) break; } insert(target,idx,ansc,ans); return ans; } void clean_table(){ int i; lnode *p,*pp; for(i=0;i<N;i++) if(table[i]){ p=table[i]; while(p){ pp=p->next; free(p); p=pp; } table[i]=NULL; } return; }
Seems like cookies are disabled on this browser, please enable them to open this website
Black and White Tree
You are viewing a single comment's thread. Return to all comments →
In C: