Fundamental/weighted/category union search

I - Union lookup set poj 1456

Problem analysis:
There are many solutions to this problem. I use a structure plus a priority queue (the structure can be replaced by a pair)
to build a structure of days and prices,
and then sort by price to
open a cnt record for the number of days (limited to 1 fruit per day) )
Sweep from the beginning to the end during this period
because there may be the same day but there are many choices.
Keep the .day of the cnt<= structure.
If it is greater than the .day, check whether the head of the team is smaller than the new one and join the team

code show as below:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
struct node
{
    
    
	int vla;
	int d;
}ans[10005];
int cmp(node a,node b)
{
    
    
	return a.d<b.d;
}
int main()
{
    
     
int n;
while(cin>>n)
{
    
    
	for(int i=0;i<n;i++)
		cin>>ans[i].vla>>ans[i].d;
   sort(ans,ans+n,cmp);
   long long sum=0;
   int cnt=1;
   priority_queue<int,vector<int>,greater<int> >q;
   for(int i=0;i<n;i++)
   {
    
    
   	   if(cnt<=ans[i].d)
   	   {
    
    
   	   	q.push(ans[i].vla);
   	   	cnt++;
		  }
		  else if(q.top()<ans[i].vla)
		  {
    
    
		  	q.pop();
		  	q.push(ans[i].vla);
		  }
   }
   while(q.size())
   {
    
    
   	sum+=q.top();
   	q.pop();
   }
   cout<<sum<<endl;
}
    return 0;
}

J - Union lookup POJ 1611

Analysis of the problem: Set the template directly and then find the number of child nodes under 0. The
code is as follows:

#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
#define mem(a)  memset(a,0,sizeof(a))
using namespace std;
int sum[30005],r[30005];
int find(int a)
{
    
    
	if(r[a]!=a)
	r[a]=find(r[a]);
	return r[a];
}
int build(int a,int b)
{
    
    
	int x=find(a);
	int y=find(b);	
	if(x!=y)
	{
    
    
		r[y]=x;
		sum[x]+=sum[y];
	}
	return 0;
}
int main()
{
    
    
 int n,m;
 while(cin>>n>>m&&n)
    {
    
    
    	for(int i=0;i<n;i++)
    	{
    
    
    		sum[i]=1;
    		r[i]=i;
		}
		while(m--)
		{
    
    
			int t,a,b;
			cin>>t>>a;
			t--;
			while(t--)
			{
    
    
				cin>>b;
				build(a,b);
			} 
		}
		cout<<sum[find(0)]<<endl;
	}	
	return 0;
}

M - weighted union hdu 3038D

Analysis of the problem:
The core of weighted union search is to update the weights.
The main formula is to update when the root is found: val[a]+=val[pr[a]];
establishing a new link is to update val[find(b)]=val[ a]+v-val[b];
Check whether the weight is in line with the same root The
code is as follows:

#include <iostream>
#include <cstring>
#include <algorithm>
#define  mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn =200005;
int  val[maxn],pr[maxn];
int find(int a)
{
    
    
   if(pr[a]==-1)
   return a;
   int t=find(pr[a]);
    val[a]+=val[pr[a]];
    return pr[a]=t;
}
int main() 
{
    
    
   int n,m,ans=0;
   while(cin>>n>>m)
   {
    
    
   	ans=0;
   	mem(val,0);
mem(pr,-1);
while(m--)
{
    
    
   int a,b,v;
   cin>>a>>b>>v;
   a--;
   int x=find(a);
   int y=find(b);
   if(x!=y)
   {
    
    
   	pr[y]=x;
   	val[y]=val[a]-val[b]+v;
    } 
    else if( val[b]-val[a]!=v)
     ans++;
}
cout<<ans<<endl;
   }

   return 0;
}

N - Kinds of Unions POJ 2492

There are 2 ways to write the .type union check set:
1: One is to open the multiple array record to check whether there is a conflict and then merge without conflict (two-way)
2: The other is to rely on an offset vector array (equivalent to the weight array God The name sounds domineering as soon as I hear it) to distinguish the types.
This question uses the first method and matches the test data . The
key is that a-b+maxn b-a+maxn establishes a relationship, but they are relatively independent relative to gender. The
same root will be found once the sex of the same gender appears. The
test outputs the meaning of each number in the formula:

Starting value - starting value rooting - process rooting - tail rooting (that is, root[a]=a case value a/root[a])

1000 4 4
1 2
a-again        1 1000002 1000002     a-end
b-maxn|-again: 2 2     b-end
b-again        1000002 1000002      b-end

a-again        2 1000001 1000001     a-end
b-maxn|-again: 1 1000002 1000002     b-end
b-again        1000001 1000001      b-end

2 3
a-again        2 1000001 1000003 1000003     a-end
b-maxn|-again: 3 3     b-end
b-again        1000003 1000003      b-end

a-again        3 1000002 1000002     a-end
b-maxn|-again: 2 1000003 1000003     b-end
b-again        1000002 1000002      b-end

1 4
a-again        1 1000002 1000004 1000004     a-end
b-maxn|-again: 4 4     b-end
b-again        1000004 1000004      b-end

a-again        4 1000003 1000003     a-end
b-maxn|-again: 1 1000004 1000004     b-end
b-again        1000001 1000003 1000003      b-end

1 3
1000004 Scenario #1:
Suspicious bugs found!

It's best to reason it out by yourself, it's a bit hard to understand... I've been watching it for a long time (seeing 0_0 for autistic... ) The
input must be scanned with scanf() or it's tle...

The code is as follows: (including the test part)

#include <iostream>
#include <cstring>
#include <algorithm>
#include<cstdio>
#define  mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn =1000000;
int  p[maxn*2],flag;
int find(int a)
{
    
    
    if( p[a]!=a)
    {
    
    
    	p[a]=find(p[a]);
    	cout<<p[a]<<" ";
	}
      
    return p[a];
}
int finds(int a)
{
    
    
    if( p[a]!=a)
    {
    
    
    	p[a]=find(p[a]);
	}
      
    return p[a];
}
int build(int a,int b)
{
    
    
	  int x,y;
	  x=finds(a);
	  y=finds(b-maxn);
	  if(x==y)
	  {
    
    
	  	flag=0;
	  	return 0;
	  }
	  y=finds(b);
	  if(x!=y)
	  {
    
    
	  	p[x]=p[y];
	  }
	  /*
	  cout<<"a-again        "<<a<<" "<<p[a]<<" ";
	  x=find(a);
	  cout<<"    a-end"<<endl;
	  cout<<"b-maxn|-again: "<<b-maxn<<" "<<p[b-maxn]<<" ";
	  y=find(b-maxn);
	  cout<<"    b-end"<<endl;
	  cout<<"b-again        "<<b<<" "<<p[b]<<" ";
	  y=find(b);
	  cout<<"     b-end"<<endl<<endl;
	  */	
}
int main() 
{
    
    
    int t,n,m,ans=0;
    scanf("%d",&t);
   for(int i=0;i<t;i++)
    {
    
    
	scanf("%d%d",&n,&m);
    	ans++;
    	for(int i=1;i<=n;i++)
    	{
    
    
    		p[i]=i;
			p[i+maxn]=maxn+i; 
		} 
    	flag=1;
      while(m--)
      {
    
    
      	int a,b;
      	scanf("%d%d",&a,&b);
      	build(a,b+maxn);
      	build(b,a+maxn);
      	} 
      	printf("Scenario #%d:\n",ans);
      	if(flag)
      	printf("No suspicious bugs found!\n");
      	else
      	printf("Suspicious bugs found!\n");
      	cout<<endl;
     }
    return 0;
}

O - Species Union POJ 1182

This is the use of the variable val[i] to distinguish the fixed value.
It took a long time to understand this thing.
Attach the great god for a comprehensive
analysis . It should be better if the analysis of the great god is simplified and combined! (Here, val is used instead of relation).
1. Partial The meaning of the value of the shift array val[] is determined
by the input relationship 1 2 (the input relationship is taken -1), so it is
stipulated that 0: the same class 1: the child is eaten by x->y 2: the child eats the parent x<-y (this way You can use %3 for compression)
2. Path compression algorithm formula
x->y->z (child->parent->father) relational expression (enumeration inference, x->y represents x is the root of y~ )
val[lord]=(vla[child]+val[father])%3 (%3 in order to prevent the occurrence of greater than or equal to 3)
and can get x->y (child is eaten 1)=y<-x( The child eats the father 3-2)
can get x->y (the child is eaten 3-1)=y<-x (the child eats the father 2)
3. The formula for determining the relationship between sets:
val[b]=(3- val [y]+(relation -1)+val[x])%3;(relation abbreviation r)
(b=find(y), b is the root of y, input: relation xy )

relation chart
X------>Y<-------B
r-1 val[y]
X------>Y------->B
r-1 3-val[y]
A----->-X------>Y------->B
val[x] r-1 val[y]

4. Judgment formula

According to the meaning of the title, a total of 4 kinds are false
1. x>n or y>n
2. r=2&&x==y
3. When a!=b
1) x==&&val[x]!=val[y]
2) x==2&&(3-val[x]+val[y])%3!=1

Illustration about 3-2)

current state Process desired state
A<—X---->Y Change down direction: 3-val[x] A—>X---->Y

Tired... Finally finished writing and crying~~ The
code is as follows:

#include <iostream>
#include <cstring>
#include <algorithm>
#include<cstdio>
#define  mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn =50010;
int  p[maxn],val[maxn];
int find(int a)
{
    
    
    int t;
    if(a==p[a])
    return a;
    t=p[a];
    p[a]=find(t);
    val[a]=(val[a]+val[t])%3;
    return p[a];
}
int main() 
{
    
    
     int n,m,ans=0;
scanf("%d%d",&n,&m);
	 for(int i=0;i<=n;i++)
     {
    
    
     	p[i]=i;
     	val[i]=0;
	 }
   while(m--)
   {
    
    
   	int relation,x,y;
scanf("%d%d%d",&relation,&x,&y);
   	if(x>n||y>n)
   	ans++;	
   	else if(relation==2&&x==y)
   		ans++;
   	else
   	{
    
    
   		int a=find(x),b=find(y);
   		if(a!=b)
   		{
    
    
   			p[b]=a;
   			val[b]=(3+relation-1+val[x]-val[y])%3;
		   }
		   else
		   {
    
    
		   	if(relation==1&&val[x]!=val[y])
		   	ans++;
		   	if(relation==2&&((3-val[x]+val[y])%3)!=1)
		   	ans++;
		   }
	}
   }
   printf("%d\n",ans);
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325810695&siteId=291194637