标签:
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 6767 | Accepted: 2616 |
Description
Input
Output
Sample Input
10 5 1 2 even 3 4 odd 5 6 even 1 6 even 7 10 odd
Sample Output
3
分析:题意:给出一个数N代表有N个数,然后给出M组数据告诉,在某段区间内所有数的和是
奇数或偶数,找出第一组矛盾的数据。
首先要确定奇偶的传递性,即奇+偶=奇,奇+奇=偶。。。。,这样很明显是种类名并查集了,除此
之外这道题还有一点,就是离散化,由于数据比较大所以要离散化,但不能用普通离散化,要保持
区间与区间之间的正确间隔,例如区间【a,b】,可变形为【0,b】-【0,a-1】,这里要注意a-1,
a-1相对于a向后有了以为,在离散化是如果所有区间都紧挨着,则导致实际中不挨着的区间在计算式
发生重和,一次为了保证离散化的正确性,在离散化是如过实际中区间确实相邻则离散化后也一定要
相邻,如果区间不相邻则离散化后区间之间要插如一些数据以保证不发生重合详见代码。
献上代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
const int maxh=100000+10;
typedef struct Edge
{
int u,v,w;
};
Edge E[maxh];
int fa[maxh],level[maxh],num[maxh];
bool cmp(int i1,int i2)
{
return i1<i2;
}
void Init(int num)
{
for(int i=0;i<=num;i++)
{
fa[i]=i;
level[i]=0;
}
}
int Find(int x)
{
if(x!=fa[x])
{
int tmp=Find(fa[x]);
level[x]=(level[x]+level[fa[x]])%2;
fa[x]=tmp;
}
return fa[x];
}
bool Union(int x,int y,int type)
{
int fx=Find(x);
int fy=Find(y);
if(fx==fy)
{
if(((level[y]-level[x]+2)%2)==type)
return true;
return false;
}
else
{
if(fx<fy)
{
fa[fy]=fx;
level[fy]=(level[x]-level[y]+type+2)%2;
}
else
{
fa[fx]=fy;
level[fx]=(level[y]-level[x]+type+2)%2;
}
return true;
}
}
int main()
{
int n,m,h,a,b,sum;
char c[10];
while(~scanf("%d%d",&n,&m))
{
h=0;
map<int,int>mp;
mp.clear();
for(int i=0;i<m;i++)
{
scanf("%d%d%s",&E[i].u,&E[i].v,c);
if(c[0]==‘e‘)E[i].w=0;
else E[i].w=1;
if(!mp[E[i].u])
{
num[h++]=E[i].u;
mp[E[i].u]=1;
}
if(!mp[E[i].v])
{
num[h++]=E[i].v;
mp[E[i].v]=1;
}
}
sort(num,num+h,cmp);
for(int i=h-1;i>0;i--)
if(num[i]!=num[i-1]+1)
num[h++]=num[i-1]+1;
sort(num,num+h,cmp);
for(int i=0;i<h;i++)
mp[num[i]]=i+1;
Init(h);
sum=m;
for(int i=0;i<m;i++)
{
if(!Union(mp[E[i].u]-1,mp[E[i].v],E[i].w))
{
sum=i;
break;
}
}
printf("%d\n",sum);
}
return 0;
}
poj 1733 Parity game 【种类并查集+离散化】
标签:
原文地址:http://blog.csdn.net/letterwuyu/article/details/45182221