Exclusive-OR
UVALive - 4487带权并查集,回去再写
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define CLR(m,a) memset(m,a,sizeof(m)) 4 const int maxn=20010; 5 int f[maxn],d[maxn]; 6 int n,q; 7 void init(){ 8 for(int i=0;i<=n;i++){ 9 f[i]=i; 10 d[i]=0; 11 } 12 } 13 14 int gf(int x){ 15 if(x!=f[x]){ 16 int r=f[x]; 17 f[x]=gf(r); 18 d[x]=d[x]^d[r]; 19 } 20 return f[x]; 21 } 22 int uni(int a,int b,int v){ 23 int pa=gf(a); 24 int pb=gf(b); 25 if(pa==pb) return (d[a]^d[b])==v; 26 if(pa==n) swap(pa,pb); 27 f[pa]=pb; 28 d[pa]=d[a]^d[b]^v; 29 return 1; 30 } 31 32 struct Ask{ 33 int p,a; 34 bool operator<(const Ask& x){ 35 return p<x.p; 36 } 37 }; 38 Ask ask[maxn<<1]; 39 int query(int k){ 40 for(int i=0;i<k;i++) ask[i].p=gf(ask[i].a); 41 sort(ask,ask+k); 42 int l=0,ans=0; 43 while(l<k){ 44 int r=l; 45 while(r+1<k&&ask[r].p==ask[r+1].p) r++; 46 int num=r-l+1; 47 if(ask[l].p!=n&&num&1) return -1; 48 for(int i=l;i<=r;i++) ans^=d[ask[i].a]; 49 l=r+1; 50 } 51 return ans; 52 } 53 int main() 54 { 55 int kase=0; 56 char c[5],s[20]; 57 while(scanf("%d%d",&n,&q)&&(n||q)){ 58 printf("Case %d: ",++kase); 59 int flag=-1; 60 init(); 61 int ct=0; 62 for(int u=0;u<q;u++){ 63 scanf("%s",c); 64 if(c[0]=='I'){ 65 ct++; 66 gets(s); 67 if(flag!=-1) continue; 68 int p,q,v; 69 int res; 70 int t=sscanf(s,"%d%d%d",&p,&q,&v); 71 if(t==2){ 72 res=uni(p,n,q); 73 }else{ 74 res=uni(p,q,v); 75 } 76 if(!res) flag=ct; 77 }else { 78 int k; 79 scanf("%d",&k); 80 for(int i=0;i<k;i++) { 81 scanf("%d",&ask[i].a); 82 } 83 if(flag!=-1) continue; 84 int res=query(k); 85 if(res==-1) puts("I don't know."); 86 else printf("%d ",res); 87 } 88 } 89 if(flag!=-1) printf("The first %d facts are conflicting. ",flag); 90 puts(""); 91 } 92 return 0; 93 }
Almost Union-Find
题意:要求实现带删除的并查集。
思路就是将要点的影响力减为0。然后开辟新的节点(代码中的id[i]就是这个用处)去合并。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define CLR(m,a) memset(m,a,sizeof(m)) 4 5 const int maxn=200010; 6 7 int f[maxn],cnt[maxn],sum[maxn]; 8 int id[maxn]; //本替关键 9 int n,m; 10 int tot; 11 void init(){ 12 for(int i=0;i<=n;i++){ 13 f[i]=i; 14 sum[i]=i; 15 cnt[i]=1; 16 id[i]=i; 17 } 18 } 19 20 int gf(int x){ 21 return x==f[x]?f[x]:f[x]=gf(f[x]); 22 } 23 24 void uni(int a,int b){ 25 int pa=gf(a); 26 int pb=gf(b); 27 if(pa!=pb){ 28 f[pa]=pb; 29 cnt[pb]+=cnt[pa]; 30 sum[pb]+=sum[pa]; 31 } 32 } 33 34 void move(int a){ 35 int pa=gf(id[a]); // 36 sum[pa]-=a; 37 cnt[pa]--; 38 //开辟新的节点 39 id[a]=++tot; 40 f[tot]=tot; 41 sum[tot]=a; 42 cnt[tot]=1; 43 } 44 45 int main(){ 46 while(scanf("%d%d",&n,&m)!=EOF){ 47 init(); 48 int c,p,q; 49 tot=n; 50 for(int i=0;i<m;i++){ 51 scanf("%d",&c); 52 if(c==3){ 53 scanf("%d",&p); 54 int pf=gf(id[p]); 55 printf("%d %d ",cnt[pf],sum[pf]); 56 }else{ 57 scanf("%d%d",&p,&q); 58 if(c==1){ 59 uni(id[p],id[q]); 60 }else{ 61 int pf=gf(id[p]),qf=gf(id[q]); 62 if(pf==qf) continue; 63 move(p); 64 uni(id[p],id[q]); 65 } 66 } 67 } 68 } 69 return 0; 70 }
Junk-Mail Filter
题意:并查集的删除.
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=2e6+10; 4 int vis[maxn]; 5 int f[maxn],b[maxn]; 6 int cnt=0; 7 int gf(int x){ 8 return x==f[x]?x:f[x]=gf(f[x]); 9 } 10 11 int main(){ 12 int n,m; 13 // freopen("in.txt","r",stdin); 14 int kase=0; 15 while(scanf("%d%d",&n,&m)&&(n||m)){ 16 char s[4]; 17 int x,y; 18 cnt=n; 19 memset(vis,0,sizeof(vis)); 20 for(int i=0;i<=n;i++) { 21 f[i]=i; 22 b[i]=i; 23 } 24 for(int i=0;i<m;i++){ 25 scanf("%s",s); 26 if(s[0]=='S'){ 27 scanf("%d",&x); 28 b[x]=cnt; 29 f[cnt]=cnt++; 30 }else{ 31 scanf("%d%d",&x,&y); 32 int pa=gf(b[x]),pb=gf(b[y]); 33 if(pa!=pb) f[pa]=pb; 34 } 35 } 36 int ans=0; 37 for(int i=0;i<n;i++){ 38 int r=gf(b[i]); 39 if(!vis[r]){ 40 ans++; 41 vis[r]=1; 42 } 43 } 44 printf("Case #%d: %d ",++kase,ans); 45 } 46 }
Warfare
HDU - 2904题意:给n个点,点权为w,相连的边的权值为点权值之和.现在要破坏一些边使得图中不存在环,问最小代价是多少(代价即为破坏边的权值)
比较水~给边排序一下,然后并查集搞
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=110; 4 5 int f[maxn]; 6 struct Edge{ 7 int u,v,w; 8 bool operator <(const Edge& a)const{ 9 return w>a.w; 10 } 11 }e[maxn*maxn]; 12 int w[maxn],g[maxn][maxn]; 13 14 int gf(int x){ 15 return x==f[x]?x:f[x]=gf(f[x]); 16 } 17 18 int main(){ 19 int t; 20 // freopen("in.txt","r",stdin); 21 scanf("%d",&t); 22 while(t--){ 23 int n; 24 memset(g,0,sizeof(g)); 25 scanf("%d",&n); 26 int u,v,m; 27 for(int i=0;i<n;i++){ 28 scanf("%d%d%d",&u,&w[i],&m); 29 for(int j=0;j<m;j++){ 30 scanf("%d",&v); 31 g[u][v]=g[v][u]=1; 32 } 33 } 34 int cnt=0; 35 int sum=0; 36 for(int i=0;i<n;i++){ 37 for(int j=i+1;j<n;j++){ 38 if(g[i][j]){ 39 e[cnt].u=i; 40 e[cnt].v=j; 41 e[cnt].w=w[i]+w[j]; 42 sum+=e[cnt].w; 43 cnt++; 44 } 45 } 46 } 47 sort(e,e+cnt); 48 for(int i=0;i<n;i++) f[i]=i; 49 int temp=0; 50 for(int i=0;i<cnt;i++){ 51 int pa=gf(e[i].u); 52 int pb=gf(e[i].v); 53 if(pa!=pb){ 54 f[pa]=pb; 55 temp+=e[i].w; 56 } 57 } 58 printf("%d ",sum-temp); 59 } 60 return 0; 61 }