BZOJ1854: [Scoi2010] Games

BZOJ1854: [Scoi2010] Games

Description

lxhgww recently got hooked on a game, in the game, he has a lot of equipment, each equipment has 2 attributes, the value of these attributes is represented by a number between [1,10000]. When he uses a certain equipment, he can only use a certain attribute of the equipment. And each type of equipment can only be used once. At the end of the game, lxhgww encountered the ultimate boss. This ultimate boss is very strange. The attribute value of the equipment used to attack him must be attacked continuously from 1 to cause damage to the boss. That is to say, at the beginning, lxhgww can only use an equipment with an attribute value of 1 to attack the boss, then can only use an equipment with an attribute value of 2 to attack the boss, and then can only use an equipment with an attribute value of 3 to attack the boss Attack the boss...and so on. Now lxhgww wants to know how many times he can attack the boss in a row at most?

Input

The first line of input is an integer N, indicating that lxhgww has N kinds of equipment. The next N lines are descriptions of the N kinds of equipment. Each line contains 2 numbers, indicating the 2 attribute values ​​of the i-th equipment.

Output

Output a line, including a number, indicating the maximum number of consecutive attacks that lxhgww can attack.

Sample Input

3
1 2
3 2
4 5

Sample Output

2

HINT

[Data range]
For 30% of the data, ensure N < = 1000
For 100% of the data, ensure N < = 1000000

Problem solving Here!

When I saw the data range of n<=100w, I was instantly stunned. . .

Then I read the question several times

For  attributes x,y of item i,  connect a directed edge  from x  and y  to i , respectively. Take the damage value as the left point, the equipment number as the right point, and find the maximum match.

So quickly fired Hungary, but TLE. Why?

Because the vis array must be cleared to false every time, the vis array is at least 1w, and of course TLE. . .

How to do it?

We can convert the vis array from bool to int, initially clear it to 0, and then open a time, +1 each time.

Then every time you judge vis(int)==time, you can achieve the effect of vis(bool)==true.

Prove? Isn't it just to judge whether vis has been modified every time. . .

Note:

1. Use the forward star to save the image .

2. If the current damage value cannot be matched, jump out directly.

Attached code:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define MAXN 1000010
using namespace std;
int n,c=1,id=0,f[MAXN],head[MAXN],vis[MAXN];
struct node{
	int next,to;
}a[MAXN<<1];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
inline void add(int x,int y){
	a[c].to=y;a[c].next=head[x];head[x]=c++;
}
bool find(int x){
	for(int i=head[x];i;i=a[i].next){
		int v=a[i].to;
		if(vis[v]!=id){
			force[v]=id;
			if(f[v]==-1||find(f[v])){
				f[v]=x;
				return true;
			}
		}
	}
	return false;
}
void work(){
	int ans=0;
	for(int i=1;i<=10000;i++){
		id++;
		if(find(i))ans++;
		else break;
	}
	printf("%d\n",ans);
}
void init(){
	int x,y;
	n=read();
	memset(f,-1,sizeof(f));
	for(int i=1;i<=n;i++){
		x=read();y=read();
		add(x,i);add(y,i);
	}
}
int main(){
	init();
	work();
	return 0;
}

However, there are more powerful algorithms for this problem - and check the set!

The first time I saw dalao's solution to a combined set of questions on the Internet, I was stunned. . .

Consider a weapon with properties a and b as an undirected edge between points a and b.

For a connected block, if there is no ring (that is, a tree), then any p-1 points in it must be satisfied.

For a connected block, if it contains a ring, then all p points must be satisfied.

Then a vis can be used to maintain this property when merging and checking sets.

Think of weights as points and weapons as edges.

If the edge added each time is to merge two connected blocks, merge the connected blocks with smaller weights to the connected blocks with larger weights, and then give vis=true with small weights 

If not, put vis=true on the vertices of the connected block.

This ensures that if a block of size N is connected:

1. Consists of N-1 edges, vis=false for the largest point, and true for others.

2. Consists of ≥N edges, and vis=true for all points.

Then at the end only one scan of vis can get the answer.

Attached code:

#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 1000010
using namespace std;
int n, fa [MAXN];
bool vis[MAXN];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline void uniun(int x,int y){
	x=find(x);y=find(y);
	if(x==y)vis[x]=true;
	else{
		if(x<y)swap(x,y);
		if (vis [y]) vis [x] = true;
		else vis [y] = true;
		fa [y] = x;
	}
}
int main(){
	int x,y;
	n=read();
	for(int i=1;i<=n+1;i++){fa[i]=i;vis[i]=false;}
	for(int i=1;i<=n;i++){
		x=read();y=read();
		uniun(x,y);
	}
	for(int i=1;i<=10001;i++)if(!vis[i]){printf("%d\n",i-1);break;}
	return 0;
}

 

Guess you like

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