题目链接:
题目大意:
- 有一些木棍,木棍两端有不同的颜色;
- 两个木棍能够排列到一块,当且仅当两个木棍相邻端点颜色一样;
- 问这些木棍能否全部链接到一块;
解题思路:
- 首先,可以将每一个颜色,看做是一个点;
- 木棍就可以看做为两个颜色之间的一条边;
- 然后就可以组成一个图;
- 问这个图是否是一个欧拉图;
- 对于每一个颜色,可以用map映射成一个数字。但是由于数据过大,用map会超时,所以改为用一个字典树来映射。在C++11中可以用unordered_map来映射,复杂度按理说是可以。然后用并查集判断所有点是否在一个图中,然后记录端点的入度和出度就可以判断出结果
字典树版本
#include<iostream>
#include<string.h>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
const int N = 500007;
vector<int>many(N, 0), Rank(N, 0), par(N);
void init()
{
for(int i=0; i<N; ++ i)
par[i] = i;
}
int Find(int x)
{
if(x == par[x])
return x;
else
return par[x] = Find(par[x]);
}
void unite(int x, int y)
{
x = Find(x);
y = Find(y);
if(x == y)
return ;
if(Rank[x] < Rank[y])
par[x] = y;
else
{
par[y] = x;
if(Rank[x] == Rank[y])
Rank[x] ++;
}
}
struct node
{
int x;
node *next[26];
node()
{
x = -1;
for(int i=0; i<26; ++ i)
next[i] = NULL;
}
};
node *root = new node();
void Insert(string &str, int n)
{
node *head = root;
size_t i = 0;
while( i < str.size())
{
if(head->next[str[i] - 'a'] == NULL)
head->next[str[i] - 'a'] = new node();
head = head->next[str[i] - 'a'];
i ++;
}
head->x = n;
}
int Search(string &str)
{
node *head = root;
size_t i = 0;
while(i < str.size())
{
if(head->next[str[i] - 'a'] == NULL)
return 0;
head = head->next[str[i] - 'a'];
i ++;
}
if(head->x == -1)
return 0;
return head->x;
}
int main()
{
ios::sync_with_stdio(false);
init();
string a, b;
int n = 0;
int x = 0, y = 0;
while(cin >> a >> b)
{
x = Search(a);
if(x == 0)
Insert(a, x = ++ n);
y = Search(b);
if(y == 0)
Insert(b, y = ++ n);
many[x] ++, many[y] ++;
unite(x, y);
}
x = 0, y = 0;
for(int i=1; i<=n; ++ i)
{
if(par[i] == i)
x ++;
if(many[i]&1)
y ++;
}
if(x > 1 || y == 1 || y > 2)
cout << "Impossible" << endl;
else
cout << "Possible" << endl;
return 0;
}
unordered_map版本
#include<iostream>
#include<string.h>
#include<vector>
#include<unordered_map>
#include<string>
#include<algorithm>
using namespace std;
const int N = 500007;
int par[N], Rank[N];
unordered_map<string, int>mp;
vector<int>many(N, 0);
void init()
{
for(int i=0; i<N; ++ i)
par[i] = i, Rank[i] = 0;
}
int Find(int x)
{
if(x == par[x])
return x;
else
return par[x] = Find(par[x]);
}
void unite(int x, int y)
{
x = Find(x);
y = Find(y);
if(x == y)
return ;
if(Rank[x] < Rank[y])
par[x] = y;
else
{
par[y] = x;
if(Rank[x] == Rank[y])
Rank[x] ++;
}
}
int main()
{
ios::sync_with_stdio(false);
init();
string a, b;
int n = 0;
while(cin >> a >> b)
{
if(mp[a] == 0)
mp[a] = ++ n;
if(mp[b] == 0)
mp[b] = ++ n;
many[mp[a]] ++, many[mp[b]] ++;
unite(mp[a], mp[b]);
}
int x = 0, y = 0;
for(int i=1; i<=n; ++ i)
{
if(par[i] == i)
x ++;
if(many[i]&1)
y ++;
}
if(x != 1 || y & 1 || y > 2)
cout << "Impossible" << endl;
else
cout << "Possible" << endl;
return 0;
}