http://msbop.openjudge.cn/bop2013/R2_C/
广义路径问题
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <utility> #include <ctime> #include <bitset> using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::stringstream; using std::make_pair; using std::getline; using std::greater; using std::endl; using std::multimap; using std::deque; using std::unique; using std::lower_bound; using std::random_shuffle; using std::bitset; using std::upper_bound; typedef long long LL; typedef unsigned long long ULL; typedef pair<int, int> PAIR; typedef multimap<int, int> MMAP; typedef LL TY; typedef long double LF; const int MAXN(500010); const int MAXM(100010); const int MAXE(100010); const int MAXK(6); const int HSIZE(31313); const int SIGMA_SIZE(26); const int MAXH(19); const int INFI((INT_MAX-1) >> 1); const ULL BASE(31); const LL LIM(10000000); const int INV(-10000); const int MOD(100000007); const double EPS(1e-7); const LF PI(acos(-1.0)); template<typename T> void checkmax(T &a, T b){if(b > a) a = b;} template<typename T> void checkmin(T &a, T b){if(b < a) a = b;} template<typename T> T ABS(const T &a){return a < 0? -a: a;} //int MS; struct HASH_MAP { int first[HSIZE]; int next[MAXN], value[MAXN]; LL state[MAXN]; int size; void init() { memset(first, -1, sizeof(first)); size = 0; } void insert(LL ts, int tv) { int h = ts%HSIZE; for(int i = first[h]; ~i; i = next[i]) if(ts == state[i]) { value[i] += tv; if(value[i] >= MOD) value[i] -= MOD; return; } // checkmax(MS, size); state[size] = ts; value[size] = tv; next[size] = first[h]; first[h] = size++; } }hm[2]; HASH_MAP *cur, *last; int N, M; char mp[10][10]; int code[9]; int Num[6]; int CAN; //每个连通分量是否包含了水龙头 int PERI; //周长 LL encode() { memset(Num, -1, sizeof(Num)); LL ret = PERI; int tcan = 0, cnt = 0; for(int i = 0; i < M; ++i) if(code[i] == 0) ret <<= 3; else { if(Num[code[i]] == -1) { Num[code[i]] = ++cnt; if(CAN&(1 << code[i])) tcan |= (1 << cnt); } ret = (ret << 3)|Num[code[i]]; } ret = (ret << 6)|tcan; return ret; } void decode(LL ts) { CAN = ts&63; ts >>= 6; for(int i = M-1; i >= 0; --i) { code[i] = ts&7; ts >>= 3; } PERI = ts; } void updata1(int x, int y, int tv) { int lc = (y == 0)? 0: code[y-1]; int uc = (x == 0)? 0: code[y]; int tcan = CAN; int tperi = PERI; if(lc == 0 && uc == 0) { code[y] = 5; PERI = tperi+4; if(mp[x][y] == 'X') CAN |= 1 << 5; cur->insert(encode(), tv); } else if(lc == 0 || uc == 0) { code[y] = lc+uc; PERI = tperi+2; if(mp[x][y] == 'X') CAN |= 1 << (lc+uc); cur->insert(encode(), tv); } else if(lc == uc) { code[y] = lc; PERI = tperi; if(mp[x][y] == 'X') CAN |= 1 << lc; cur->insert(encode(), tv); } else { int tc1 = (CAN&(1 << lc))? lc: uc; int tc2 = lc^uc^tc1; for(int i = 0; i < M; ++i) if(code[i] == tc2) code[i] = tc1; code[y] = tc1; PERI = tperi; if(mp[x][y] == 'X') CAN |= 1 << tc1; cur->insert(encode(), tv); } } void updata2(int x, int y, int tv) { int lc = (y == 0)? 0: code[y-1]; int uc = (x == 0)? 0: code[y]; if(lc == 0 && uc == 0) { code[y] = 0; cur->insert(encode(), tv); } else if(lc == 0 || uc == 0) { if(lc) { code[y] = 0; cur->insert(encode(), tv); } else { int cnt = 0; for(int i = 0; i < M; ++i) if(code[i] == uc) ++cnt; if(cnt == 1 && (CAN&(1 << uc)) == 0) return; code[y] = 0; cur->insert(encode(), tv); } } else { int cnt = 0; for(int i = 0; i < M; ++i) if(code[i] == uc) ++cnt; if(cnt == 1 && (CAN&(1 << uc)) == 0) return; code[y] = 0; cur->insert(encode(), tv); } } void solve() { cur = hm; last = hm+1; last->init(); last->insert(0, 1); for(int i = 0; i < N; ++i) for(int j = 0; j < M; ++j) { cur->init(); int sz = last->size; for(int k = 0; k < sz; ++k) { decode(last->state[k]); if(mp[i][j] != 'T') { updata1(i, j, last->value[k]); decode(last->state[k]); } updata2(i, j, last->value[k]); } swap(cur, last); } map<int, int> ans; int sz = last->size; for(int i = 0; i < sz; ++i) { decode(last->state[i]); bool flag(true); for(int j = 0; j < M; ++j) if(code[j] && (CAN&(1 << code[j])) == 0) { flag = false; break; } if(flag) { if(ans.find(PERI) == ans.end()) ans.insert(make_pair(PERI, last->value[i])); else { ans[PERI] += last->value[i]; if(ans[PERI] >= MOD) ans[PERI] -= MOD; } } } map<int, int>::iterator it = ans.begin(); ++it; while(it != ans.end()) { printf("%d %d\n", it->first, it->second); ++it; } } int main() { int TC, n_case(0); scanf("%d", &TC); while(TC--) { scanf("%d%d", &N, &M); for(int i = 0; i < N; ++i) scanf("%s", mp[i]); printf("Case #%d:\n", ++n_case); solve(); } return 0; }