题意是一次装入物品,物品由两种元素组成,当遇到即将装入的物品与已经装入的物品形成k个物品,k种元素,跳过该物品的装入。可以将每种元素看成顶点,物品看成一条边。这样问题就转化为利用并查集求环的情况。
算法竞赛训练指南中的代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <climits> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cmath> 7 #include <vector> 8 #include <queue> 9 #include <algorithm> 10 #define esp 1e-6 11 #define pb push_back 12 #define in freopen("in.txt", "r", stdin); 13 #define out freopen("out.txt", "w", stdout); 14 #define print(a) printf("%d ",(a)); 15 #define bug puts("********))))))"); 16 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++) 17 #define inf 0x0f0f0f0f 18 using namespace std; 19 typedef long long LL; 20 typedef vector<int> VI; 21 typedef pair<int, int> pii; 22 typedef vector<pii,int> VII; 23 typedef vector<int>:: iterator IT; 24 25 #define N (int)(1e5+100) 26 int pa[N], rank[N]; 27 void init(void) 28 { 29 for(int i = 0; i < N; i++) 30 pa[i] = i; 31 memset(rank, 0, sizeof(rank)); 32 } 33 void merge(int x, int y) 34 { 35 if(rank[x] > rank[y]) 36 pa[y] = x; 37 else { 38 pa[x] = y; 39 if(rank[x] == rank[y]) 40 rank[y]++; 41 } 42 } 43 int findset(int x) 44 { 45 return (pa[x] == x) ? x: pa[x] = findset(pa[x]); 46 } 47 int main(void) 48 { 49 int x, y; 50 while(~scanf("%d", &x)) 51 { 52 int cnt = 0; 53 init(); 54 while(x != -1) 55 { 56 scanf("%d", &y); 57 x = findset(x), y = findset(y); 58 if(x == y) 59 cnt++; 60 else merge(x, y); 61 scanf("%d", &x); 62 } 63 printf("%d ", cnt); 64 } 65 return 0; 66 }