poj 1733(带权并查集+离散化)

题目链接:http://poj.org/problem?id=1733

思路:这题一看就想到要用并查集做了,不过一看数据这么大,感觉有点棘手,其实,我们仔细一想可以发现,我们需要记录的是出现过的节点到根节点的1个奇偶性,这与区间端点的大小并没有关系,于是想到我们可以用map映射即可,这样就解决了大数据了。此外,如果0表示出现偶数个1,1表示出现奇数个1,然后就是向量偏移关系了(http://www.cnblogs.com/wally/archive/2013/06/10/3130527.html).

 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<map>

 6 using namespace std;

 7 #define MAXN 5050

 8 

 9 int parent[MAXN];

10 int kind[MAXN];

11 int n,m,Index;

12 

13 void Initiate()

14 {

15     for(int i=0;i<MAXN;i++){

16         parent[i]=i;

17     }

18     memset(kind,0,sizeof(kind));

19 }

20 

21 int Find(int x)

22 {

23     if(x==parent[x]){

24         return parent[x];

25     }

26     int tmp=Find(parent[x]);

27     kind[x]=(kind[x]+kind[parent[x]])%2;

28     return parent[x]=tmp;

29 }

30 

31 bool Union(int u,int v,int d)

32 {

33     int r1=Find(u),r2=Find(v);

34     if(r1==r2){

35         if(kind[u]!=(kind[v]+d)%2)return false;

36         return true;

37     }

38     parent[r1]=r2;

39     kind[r1]=(kind[v]-kind[u]+d+2)%2;

40     return true;

41 }

42 

43 int main()

44 {

45     int a,b,d,pos;

46     char str[11];

47     while(~scanf("%d%d",&n,&m)){

48         Index=0;

49         map<int,int>mp;

50         bool flag=true;

51         Initiate();

52         for(int i=0;i<m;i++){

53             scanf("%d%d%s",&a,&b,str);

54             d=(str[0]=='e'?0:1);a--;

55             if(mp.find(a)==mp.end()){

56                 mp[a]=Index++;

57             }

58             if(mp.find(b)==mp.end()){

59                 mp[b]=Index++;

60             }

61             if(!flag)continue;

62             if(!Union(mp[a],mp[b],d)){

63                 flag=false;

64                 pos=i;

65             }

66         }

67         if(flag)pos=m;

68         printf("%d\n",pos);

69     }

70     return 0;

71 }

72 

73                 

74                 

75             

76         

77         

78 

79     
View Code

 

你可能感兴趣的:(poj)