*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LMX_API
namespace lmx
{
class BaseAllocator
{
public:
virtual void* malloc(int size) = 0;
virtual void* mallocv(int size, int value = 0) = 0;
virtual void free(void * p) = 0;
virtual ~BaseAllocator() = 0;
};
// 分配空间的类,应付poj,速度优先
class PojAllocator : public BaseAllocator
{
int pos;
public:
PojAllocator();
~PojAllocator();
void* malloc(int size);
void* mallocv(int size, int value = 0);
void free(void * p);
void reset();
};
PojAllocator g_PojAlloc;
}
#define LMX_POJ_SIZE 4000000
static char poj_buf[LMX_POJ_SIZE];
lmx::BaseAllocator::~BaseAllocator(){}
lmx::PojAllocator::PojAllocator() : pos(0){}
lmx::PojAllocator::~PojAllocator(){}
void* lmx::PojAllocator::malloc(int size){ void * p = &poj_buf[pos]; pos+=size; return p; }
void* lmx::PojAllocator::mallocv(int size, int value){ void *p = &poj_buf[pos]; pos+=size; memset(p, value, size); return p;}
void lmx::PojAllocator::free(void * p){}
void lmx::PojAllocator::reset(){ pos = 0; }
namespace lmx
{
// shortest path
struct GraphEdge
{
int v;
int value;
struct GraphEdge * next;
};
struct EdgePath
{
int u;
GraphEdge * p; // 就是指边 u -> (p->v)
};
class LMX_API NormalGraph
{
public:
BaseAllocator *pAlloc;
int N;
GraphEdge ** ppEdge;
public:
NormalGraph(int i_n, BaseAllocator *palloc = &g_PojAlloc);
~NormalGraph();
void AddEdge(int u, int v, int value);
};
class LMX_API Prim : public NormalGraph
{
public:
int s;
bool *used;
int *d;
bool bCalculated;
EdgePath *pPred; // 记录最短路径的具体路线
public:
Prim(int i_n, int i_s, BaseAllocator *palloc = &g_PojAlloc);
~Prim();
void Calculate();
};
}
lmx::NormalGraph::NormalGraph(int i_n, BaseAllocator *palloc) : N(i_n), pAlloc(palloc)
{
ppEdge = (GraphEdge **)pAlloc->mallocv(N*sizeof(void*));
}
lmx::NormalGraph::~NormalGraph()
{
GraphEdge *p, *q;
for (int i = 0; i < N; i++)
{
p = ppEdge[i];
while (p != NULL)
{
q = p->next;
pAlloc->free(p);
p = q;
}
}
pAlloc->free(ppEdge);
}
void lmx::NormalGraph::AddEdge(int u, int v, int value)
{
GraphEdge *p = (GraphEdge *)pAlloc->mallocv(sizeof(GraphEdge));
p->v = v;
p->value = value;
p->next = ppEdge[u];
ppEdge[u] = p;
}
#define LMX_SP_MAX_VALUE 0x77777777
lmx::Prim::Prim(int i_n, int i_s, BaseAllocator *palloc) : NormalGraph(i_n, palloc), s(i_s), bCalculated(false)
{
used = (bool*)pAlloc->mallocv(N*sizeof(bool));
d = (int*)pAlloc->mallocv(N*sizeof(int), 0x77);
pPred = (EdgePath*)pAlloc->mallocv(N*sizeof(EdgePath));
}
lmx::Prim::~Prim()
{
pAlloc->free(used);
pAlloc->free(d);
pAlloc->free(pPred);
}
void lmx::Prim::Calculate()
{
if (bCalculated) return;
bCalculated = true;
d[s] = 0;
int i, j, k;
GraphEdge *p;
for (i = 0; i < N; i++)
{
j = -1;
for (k = 0; k < N; k++)
if (!used[k] && d[k] < LMX_SP_MAX_VALUE && (j == -1 || d[j] > d[k]))
j = k;
if (j == -1) break;
used[j] = true;
p = ppEdge[j];
while (p != NULL)
{
if (!used[p->v] && d[p->v] > p->value)
{
d[p->v] = p->value;
pPred[p->v].u = j;
pPred[p->v].p = p;
}
p = p->next;
}
}
}
int n, w, h, m;
char maze[64][64];
int step[128][128];
int line[64*64];
bool used[64*64];
int d[4][2] = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } };
void bfs(int i, int j)
{
int a = (int)((unsigned char )maze[i][j]) - 128;
int len = 1, f = 0, r, u, v;
memset(used, 0, sizeof(used));
line[0] = i<<6|j;
used[line[0]] = true;
int c = 0;
while (true)
{
c++;
r = len;
for (int k = f; k < len; k++)
for (int l = 0; l < 4; l++)
{
u = (line[k]>>6) + d[l][0];
v = (line[k]&63) + d[l][1];
if (u >= 0 && u < h && v >= 0 && v < w && maze[u][v] != '#'){
if (!used[u<<6|v]){
line[r] = u<<6|v;
used[line[r]] = true;
if (maze[u][v] != ' '){
step[a][(int)((unsigned char )maze[u][v]) - 128] = c;
}
r++;
}
}
}
if (r == len)
break;
f = len;
len = r;
}
}
int main(int argc, char* argv[])
{
int i, j, k;
scanf("%d", &n);
while (n--)
{
scanf("%d%d", &w, &h);
gets(maze[0]);
for (i = 0; i < h; i++)
gets(maze[i]);
m = 0;
for (i = 0; i < h; i++)
for (j = 0; j < w; j++)
if (maze[i][j] == 'A' || maze[i][j] == 'S')
{
maze[i][j] = 128 + m;
m++;
}
for (i = 0; i < h; i++)
for (j = 0; j < w; j++)
if (maze[i][j] != ' ' && maze[i][j] != '#')
bfs(i, j);
lmx::g_PojAlloc.reset();
lmx::Prim prim(m, 0);
for (i = 0; i < m-1; i++)
for (j = i+1; j < m; j++)
{
prim.AddEdge(i, j, step[i][j]);
prim.AddEdge(j, i, step[j][i]);
}
prim.Calculate();
k = 0;
for (i = 0; i < m; i++)
k += prim.d[i];
printf("%d\n", k);
}
return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LMX_API
namespace lmx
{
class BaseAllocator
{
public:
virtual void* malloc(int size) = 0;
virtual void* mallocv(int size, int value = 0) = 0;
virtual void free(void * p) = 0;
virtual ~BaseAllocator() = 0;
};
// 分配空间的类,应付poj,速度优先
class PojAllocator : public BaseAllocator
{
int pos;
public:
PojAllocator();
~PojAllocator();
void* malloc(int size);
void* mallocv(int size, int value = 0);
void free(void * p);
void reset();
};
PojAllocator g_PojAlloc;
}
#define LMX_POJ_SIZE 4000000
static char poj_buf[LMX_POJ_SIZE];
lmx::BaseAllocator::~BaseAllocator(){}
lmx::PojAllocator::PojAllocator() : pos(0){}
lmx::PojAllocator::~PojAllocator(){}
void* lmx::PojAllocator::malloc(int size){ void * p = &poj_buf[pos]; pos+=size; return p; }
void* lmx::PojAllocator::mallocv(int size, int value){ void *p = &poj_buf[pos]; pos+=size; memset(p, value, size); return p;}
void lmx::PojAllocator::free(void * p){}
void lmx::PojAllocator::reset(){ pos = 0; }
#define LMX_TRIE_NUM 4
namespace lmx
{
struct TrieNode
{
int nRunCount; // 路过的次数
int nEndCount; // 串在此终结的次数
TrieNode *son[LMX_TRIE_NUM];
TrieNode *p; // 父节点
char value;
TrieNode * failed; // 失败指针
TrieNode * next; // 配合bfs,做链表
int reserve;
};
class LMX_API Trie
{
public:
TrieNode *root;
BaseAllocator *pAlloc;
public:
Trie(BaseAllocator *palloc = &g_PojAlloc);
~Trie();
void Insert(char *s, int len); // 插入一个串
void Delete(char *s, int len); // 删除一个串
void Delete(TrieNode *ptn); // 删除一个串
void Deletes(TrieNode *ptn); // 删除一个节点,包括子节点
TrieNode * Find(char *s, int len);
void CalFailedPoint();
int ModifyCount(char *s, int len);
};
}
lmx::Trie::Trie(BaseAllocator *palloc) : pAlloc(palloc)
{
root = (TrieNode*)pAlloc->mallocv(sizeof(TrieNode));
}
lmx::Trie::~Trie(){ Deletes(root); }
void lmx::Trie::Insert(char *s, int len)
{
TrieNode *p = root;
p->nRunCount++;
for (int i = 0; i < len; i++){
if (p->son[s[i]] == NULL){
p->son[s[i]] = (TrieNode*)pAlloc->mallocv(sizeof(TrieNode));
p->son[s[i]]->value = s[i];
p->son[s[i]]->p = p;
}
p = p->son[s[i]];
p->nRunCount++;
}
p->nEndCount++;
}
void lmx::Trie::Delete(char *s, int len)
{
TrieNode *p = Find(s, len);
if (p != NULL)
Delete(p);
}
void lmx::Trie::Delete(TrieNode *ptn)
{
if (ptn->nEndCount == 0) return;
ptn->nEndCount--;
TrieNode *p, *q = ptn;
while (q != NULL)
{
p = q->p;
q->nRunCount--;
if (q->nRunCount == 0 && q != root){
p->son[q->value] = NULL;
pAlloc->free(q);
}
q = p;
}
}
void lmx::Trie::Deletes(TrieNode *ptn)
{
for (int i = 0; i < LMX_TRIE_NUM; i++)
if (ptn->son[i] != NULL)
Deletes(ptn->son[i]);
if (ptn != root)
ptn->p->son[ptn->value] = NULL;
pAlloc->free(ptn);
}
lmx::TrieNode * lmx::Trie::Find(char *s, int len)
{
TrieNode *p = root;
for (int i = 0; i < len; i++){
if (p->son[s[i]] == NULL)
return NULL;
p = p->son[s[i]];
}
return p->nEndCount > 0 ? p : NULL;
}
void lmx::Trie::CalFailedPoint()
{
TrieNode *line = root; // 当前list
TrieNode *r = NULL, *rr= NULL; // 新生成的list
TrieNode *p, *q;
while (true)
{
for (p = line; p != NULL; p = p->next)
{
for (int i = 0; i < LMX_TRIE_NUM; i++)
if (p->son[i] != NULL){
q = p->failed;
while (q != NULL){
if (q->son[i] != NULL){
p->son[i]->failed = q->son[i];
break;
}
q = q->failed;
}
if (q == NULL)
p->son[i]->failed = root;
if (r == NULL){
r = rr = p->son[i];
}else{
rr->next = p->son[i];
rr = p->son[i];
}
}
if (p->next == NULL){
p->next = r;
break;
}
}
if (r == NULL)
break;
line = r;
r = NULL;
}
}
int lmx::Trie::ModifyCount(char *s, int len)
{
TrieNode *p, *q;
int L = 0, t;
for (p = root; p != NULL; p = p->next)
{
if (p != root &&
( p->nEndCount ||
p->p->reserve == -1 ||
p->failed->reserve == -1) )
p->reserve = -1;
if (p->reserve == -1) continue;
p->reserve = L++;
}
int *a = (int*)pAlloc->mallocv(L*sizeof(int), -1);
int *b = (int*)pAlloc->mallocv(L*sizeof(int), -1);
a[root->reserve] = 0;
for (int k = 0; k < len; k++)
{
for (p = root; p != NULL; p = p->next)
{
if (p->reserve == -1 || a[p->reserve] == -1) continue;
for (int i = 0; i < LMX_TRIE_NUM; i++)
{
t = a[p->reserve];
if (i != s[k]) t++;
q = p;
while (q != NULL)
{
if (q->son[i] != NULL){
if (q->son[i]->reserve != -1)
{
if (b[q->son[i]->reserve] == -1 || b[q->son[i]->reserve] > t)
b[q->son[i]->reserve] = t;
}
break;
}
q = q->failed;
}
if (q == NULL)
{
if (b[root->reserve] == -1 || b[root->reserve] > t)
b[root->reserve] = t;
}
}
}
memcpy(a, b, L*sizeof(int));
memset(b, -1, L*sizeof(int));
}
t = -1;
for (int i = 0; i < L; i++)
if (a[i] != -1 && (t == -1 || t >a[i]))
t = a[i];
pAlloc->free(a);
pAlloc->free(b);
return t;
}
int main(int argc, char* argv[])
{
int i, j, len, cases = 0;
char s[1024];
int N;
for (;;)
{
scanf("%d", &N);
if (N == 0) break;
lmx::g_PojAlloc.reset();
lmx::Trie tr;
for (i = 0; i <= N; i++)
{
scanf("%s", s);
len = strlen(s);
for (j = 0; j < len; j++)
if (s[j] == 'A') s[j] = 0;
else if (s[j] == 'C') s[j] = 1;
else if (s[j] == 'T') s[j] = 2;
else s[j] = 3;
if (i != N)
tr.Insert(s, len);
}
tr.CalFailedPoint();
cases++;
printf("Case %d: %d\n", cases, tr.ModifyCount(s, len));
}
return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LMX_API
namespace lmx
{
class BaseAllocator
{
public:
virtual void* malloc(int size) = 0;
virtual void* mallocv(int size, int value = 0) = 0;
virtual void free(void * p) = 0;
virtual ~BaseAllocator() = 0;
};
// 分配空间的类,应付poj,速度优先
class PojAllocator : public BaseAllocator
{
int pos;
public:
PojAllocator();
~PojAllocator();
void* malloc(int size);
void* mallocv(int size, int value = 0);
void free(void * p);
void reset();
};
PojAllocator g_PojAlloc;
}
#define LMX_POJ_SIZE 4000000
static char poj_buf[LMX_POJ_SIZE];
lmx::BaseAllocator::~BaseAllocator(){}
lmx::PojAllocator::PojAllocator() : pos(0){}
lmx::PojAllocator::~PojAllocator(){}
void* lmx::PojAllocator::malloc(int size){ void * p = &poj_buf[pos]; pos+=size; return p; }
void* lmx::PojAllocator::mallocv(int size, int value){ void *p = &poj_buf[pos]; pos+=size; memset(p, value, size); return p;}
void lmx::PojAllocator::free(void * p){}
void lmx::PojAllocator::reset(){ pos = 0; }
#define LMX_TRIE_NUM 4
namespace lmx
{
struct TrieNode
{
int nRunCount; // 路过的次数
int nEndCount; // 串在此终结的次数
TrieNode *son[LMX_TRIE_NUM];
TrieNode *p; // 父节点
char value;
TrieNode * failed; // 失败指针
TrieNode * next; // 配合bfs,做链表
int reserve;
};
class LMX_API Trie
{
public:
TrieNode *root;
BaseAllocator *pAlloc;
public:
Trie(BaseAllocator *palloc = &g_PojAlloc);
~Trie();
void Insert(char *s, int len); // 插入一个串
void Delete(char *s, int len); // 删除一个串
void Delete(TrieNode *ptn); // 删除一个串
void Deletes(TrieNode *ptn); // 删除一个节点,包括子节点
TrieNode * Find(char *s, int len);
void CalFailedPoint();
int GetBaseMatrix(int baseMatrix[][128]);
};
}
lmx::Trie::Trie(BaseAllocator *palloc) : pAlloc(palloc)
{
root = (TrieNode*)pAlloc->mallocv(sizeof(TrieNode));
}
lmx::Trie::~Trie(){ Deletes(root); }
void lmx::Trie::Insert(char *s, int len)
{
TrieNode *p = root;
p->nRunCount++;
for (int i = 0; i < len; i++){
if (p->son[s[i]] == NULL){
p->son[s[i]] = (TrieNode*)pAlloc->mallocv(sizeof(TrieNode));
p->son[s[i]]->value = s[i];
p->son[s[i]]->p = p;
}
p = p->son[s[i]];
p->nRunCount++;
}
p->nEndCount++;
}
void lmx::Trie::Delete(char *s, int len)
{
TrieNode *p = Find(s, len);
if (p != NULL)
Delete(p);
}
void lmx::Trie::Delete(TrieNode *ptn)
{
if (ptn->nEndCount == 0) return;
ptn->nEndCount--;
TrieNode *p, *q = ptn;
while (q != NULL)
{
p = q->p;
q->nRunCount--;
if (q->nRunCount == 0 && q != root){
p->son[q->value] = NULL;
pAlloc->free(q);
}
q = p;
}
}
void lmx::Trie::Deletes(TrieNode *ptn)
{
for (int i = 0; i < LMX_TRIE_NUM; i++)
if (ptn->son[i] != NULL)
Deletes(ptn->son[i]);
if (ptn != root)
ptn->p->son[ptn->value] = NULL;
pAlloc->free(ptn);
}
lmx::TrieNode * lmx::Trie::Find(char *s, int len)
{
TrieNode *p = root;
for (int i = 0; i < len; i++){
if (p->son[s[i]] == NULL)
return NULL;
p = p->son[s[i]];
}
return p->nEndCount > 0 ? p : NULL;
}
void lmx::Trie::CalFailedPoint()
{
TrieNode *line = root; // 当前list
TrieNode *r = NULL, *rr= NULL; // 新生成的list
TrieNode *p, *q;
while (true)
{
for (p = line; p != NULL; p = p->next)
{
for (int i = 0; i < LMX_TRIE_NUM; i++)
if (p->son[i] != NULL){
q = p->failed;
while (q != NULL){
if (q->son[i] != NULL){
p->son[i]->failed = q->son[i];
break;
}
q = q->failed;
}
if (q == NULL)
p->son[i]->failed = root;
if (r == NULL){
r = rr = p->son[i];
}else{
rr->next = p->son[i];
rr = p->son[i];
}
}
if (p->next == NULL){
p->next = r;
break;
}
}
if (r == NULL)
break;
line = r;
r = NULL;
}
}
int lmx::Trie::GetBaseMatrix(int baseMatrix[][128])
{
for (int i = 0; i < 128; i++)
memset(baseMatrix[i], 0, 128*sizeof(int));
TrieNode *p, *q;
int L = 0;
for (p = root; p != NULL; p = p->next)
{
if (p != root &&
( p->nEndCount ||
p->p->reserve == -1 ||
p->failed->reserve == -1) )
p->reserve = -1;
if (p->reserve == -1) continue;
p->reserve = L++;
}
for (p = root; p != NULL; p = p->next)
{
if (p->reserve == -1) continue;
for (int i = 0; i < LMX_TRIE_NUM; i++)
{
q = p;
while (q != NULL)
{
if (q->son[i] != NULL){
if (q->son[i]->reserve != -1)
baseMatrix[p->reserve][q->son[i]->reserve]++;
break;
}
q = q->failed;
}
if (q == NULL)
baseMatrix[p->reserve][0]++;
}
}
return L;
}
#define MODM 100000
int re[128][128], base[128][128], temp[128][128], temp2[128][128];
int m, n;
char s[16];
void MultiplyMatrix(const int a[][128], const int b[][128], int c[][128], int L)
{
for (int i = 0; i < L; i++)
for (int j = 0; j < L; j++)
{
__int64 t = 0;
for (int k = 0; k < L; k++)
t += (__int64)a[i][k] * b[k][j];
c[i][j] = t%MODM;
}
}
int main(int argc, char* argv[])
{
int i, j, len;
scanf("%d%d", &m, &n);
lmx::Trie tr;
for (i = 0; i < m; i++)
{
scanf("%s", s);
len = strlen(s);
for (j = 0; j < len; j++)
if (s[j] == 'A') s[j] = 0;
else if (s[j] == 'C') s[j] = 1;
else if (s[j] == 'T') s[j] = 2;
else s[j] = 3;
tr.Insert(s, len);
}
tr.CalFailedPoint();
int L = tr.GetBaseMatrix(base);
for (i = 0; i < L; i++) re[i][i] = 1;
for (i = 0; i < 31; i++)
{
if (n & (1<<i)){
MultiplyMatrix(re, base, temp, L);
memcpy(re, temp, sizeof(re));
}
MultiplyMatrix(base, base, temp, L);
memcpy(base, temp, sizeof(base));
}
int sum = 0;
for (i = 0; i < L; i++)
sum += re[0][i];
sum %= MODM;
printf("%d\n", sum);
return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <deque>
#define LMX_API
namespace lmx
{
class BaseAllocator
{
public:
virtual void* malloc(int size) = 0;
virtual void* mallocv(int size, int value = 0) = 0;
virtual void free(void * p) = 0;
virtual ~BaseAllocator() = 0;
};
// 分配空间的类,应付poj,速度优先
class LMX_API PojAllocator : public BaseAllocator
{
int pos;
public:
PojAllocator();
~PojAllocator();
void* malloc(int size);
void* mallocv(int size, int value = 0);
void free(void * p);
void reset();
};
LMX_API extern PojAllocator g_PojAlloc;
}
#define LMX_POJ_SIZE 4000000
static char poj_buf[LMX_POJ_SIZE];
lmx::BaseAllocator::~BaseAllocator(){}
lmx::PojAllocator::PojAllocator() : pos(0){}
lmx::PojAllocator::~PojAllocator(){}
void* lmx::PojAllocator::malloc(int size){ void * p = &poj_buf[pos]; pos+=size; return p; }
void* lmx::PojAllocator::mallocv(int size, int value){ void *p = &poj_buf[pos]; pos+=size; memset(p, value, size); return p;}
void lmx::PojAllocator::free(void * p){}
void lmx::PojAllocator::reset(){ pos = 0; }
lmx::PojAllocator lmx::g_PojAlloc;
namespace lmx
{
// shortest path
struct GraphEdge
{
int v;
int value;
struct GraphEdge * next;
};
struct EdgePath
{
int u;
GraphEdge * p; // 就是指边 u -> (p->v)
};
class LMX_API NormalGraph
{
public:
int N;
GraphEdge ** ppEdge;
BaseAllocator* pAlloc;
public:
NormalGraph(int i_n, BaseAllocator *palloc = &g_PojAlloc);
~NormalGraph();
void AddEdge(int u, int v, int value);
};
// 先不自己实现队列了,有点麻烦
class LMX_API Spfa : public NormalGraph
{
public:
int s;
bool *used;
int *d;
bool bCalculated;
bool bAnnulus; // true表示有负环
EdgePath *pPred; // 记录最短路径的具体路线
int* pCounts;
std::deque<int> *pque;
public:
Spfa(int i_n, int i_s, BaseAllocator *palloc = &g_PojAlloc);
~Spfa();
void Calculate();
};
class LMX_API SpBeelmanFord : public NormalGraph
{
public:
int s;
int *d;
bool bCalculated;
bool bAnnulus; // true表示有负环
EdgePath *pPred; // 记录最短路径的具体路线
public:
SpBeelmanFord(int i_n, int i_s, BaseAllocator *palloc = &g_PojAlloc);
~SpBeelmanFord();
void Calculate();
};
}
lmx::NormalGraph::NormalGraph(int i_n, BaseAllocator *palloc) : N(i_n), pAlloc(palloc)
{
ppEdge = (GraphEdge **)pAlloc->mallocv(N*sizeof(void*));
}
lmx::NormalGraph::~NormalGraph()
{
GraphEdge *p, *q;
for (int i = 0; i < N; i++)
{
p = ppEdge[i];
while (p != NULL)
{
q = p->next;
pAlloc->free(p);
p = q;
}
}
pAlloc->free(ppEdge);
}
void lmx::NormalGraph::AddEdge(int u, int v, int value)
{
GraphEdge *p = (GraphEdge *)pAlloc->mallocv(sizeof(GraphEdge));
p->v = v;
p->value = value;
p->next = ppEdge[u];
ppEdge[u] = p;
}
lmx::Spfa::Spfa(int i_n, int i_s, BaseAllocator *palloc) : NormalGraph(i_n, palloc), s(i_s), bCalculated(false)
{
used = (bool*)pAlloc->mallocv(N*sizeof(bool));
d = (int*)pAlloc->mallocv(N*sizeof(int), 0x77);
pCounts = (int*)pAlloc->mallocv(N*sizeof(int));
pPred = (EdgePath*)pAlloc->mallocv(N*sizeof(EdgePath));
pque = new std::deque<int>();
}
lmx::Spfa::~Spfa()
{
pAlloc->free(used);
pAlloc->free(d);
pAlloc->free(pCounts);
pAlloc->free(pPred);
}
void lmx::Spfa::Calculate()
{
if (bCalculated) return;
bAnnulus = false;
bCalculated = true;
d[s] = 0;
pque->push_back(s);
pCounts[s]++;
used[s] = true;
int j, k;
GraphEdge *p;
while (!pque->empty())
{
j = pque->front();
pque->pop_front();
used[j] = false;
p = ppEdge[j];
while (p != NULL)
{
if (d[p->v] > d[j]+p->value)
{
d[p->v] = d[j]+p->value;
pPred[p->v].u = j;
pPred[p->v].p = p;
if (!used[p->v])
{
if (pque->empty()) pque->push_back(p->v);
else{
k = pque->front();
if (d[p->v] < d[k]) pque->push_front(p->v);
else pque->push_back(p->v);
}
used[p->v] = true;
pCounts[p->v]++;
if (pCounts[p->v] >= N)
{
bAnnulus = true;
return;
}
}
}
p = p->next;
}
}
}
#define LMX_SP_MAX_VALUE 0x77777777
lmx::SpBeelmanFord::SpBeelmanFord(int i_n, int i_s, BaseAllocator *palloc) : NormalGraph(i_n, palloc), s(i_s), bCalculated(false)
{
d = (int*)pAlloc->mallocv(N*sizeof(int), 0x77);
pPred = (EdgePath*)pAlloc->mallocv(N*sizeof(EdgePath));
}
lmx::SpBeelmanFord::~SpBeelmanFord()
{
pAlloc->free(d);
pAlloc->free(pPred);
}
void lmx::SpBeelmanFord::Calculate()
{
if (bCalculated) return;
bAnnulus = false;
bCalculated = true;
d[s] = 0;
int i, j;
GraphEdge *p;
for (i = 0; i < N-1; i++)
{
for (j = 0; j < N; j++)
{
if (d[j] == LMX_SP_MAX_VALUE) continue;
p = ppEdge[j];
while (p != NULL)
{
if (d[p->v] > d[j]+p->value)
{
d[p->v] = d[j]+p->value;
pPred[p->v].u = j;
pPred[p->v].p = p;
}
p = p->next;
}
}
}
for (i = 0; i < N-1; i++)
{
for (j = 0; j < N; j++)
{
if (d[j] == LMX_SP_MAX_VALUE) continue;
p = ppEdge[j];
while (p != NULL)
{
if (d[p->v] > d[j]+p->value)
{
bAnnulus = true;
return;
}
p = p->next;
}
}
}
}
int main()
{
int N, M;
int a, b, x, i;
char s[8];
while (scanf("%d%d", &N, &M) == 2)
{
lmx::g_PojAlloc.reset();
lmx::Spfa sp(N+1, 0);
for (i = 0; i < M; i++)
{
scanf("%s", s);
if (s[0] == 'P'){
scanf("%d%d%d", &a, &b, &x);
sp.AddEdge(b, a, x);
sp.AddEdge(a, b, -x);
}else{
scanf("%d%d", &a, &b);
sp.AddEdge(a, b, -1);
}
}
for (i = 1; i <= N; i++)
sp.AddEdge(0, i, 0);
sp.Calculate();
if (sp.bAnnulus) printf("Unreliable\n");
else printf("Reliable\n");
}
return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LMX_API
namespace lmx
{
class BaseAllocator
{
public:
virtual void* malloc(int size) = 0;
virtual void* mallocv(int size, int value = 0) = 0;
virtual void free(void * p) = 0;
virtual ~BaseAllocator() = 0;
};
// 分配空间的类,应付poj,速度优先
class PojAllocator : public BaseAllocator
{
int pos;
public:
PojAllocator();
~PojAllocator();
void* malloc(int size);
void* mallocv(int size, int value = 0);
void free(void * p);
void reset();
};
extern PojAllocator g_PojAlloc;
}
#define LMX_POJ_SIZE 4000000
static char poj_buf[LMX_POJ_SIZE];
lmx::BaseAllocator::~BaseAllocator(){}
lmx::PojAllocator::PojAllocator() : pos(0){}
lmx::PojAllocator::~PojAllocator(){}
void* lmx::PojAllocator::malloc(int size){ void * p = &poj_buf[pos]; pos+=size; return p; }
void* lmx::PojAllocator::mallocv(int size, int value){ void *p = &poj_buf[pos]; pos+=size; memset(p, value, size); return p;}
void lmx::PojAllocator::free(void * p){}
void lmx::PojAllocator::reset(){ pos = 0; }
lmx::PojAllocator lmx::g_PojAlloc;
namespace lmx
{
// network stream
struct NsEdge
{
int v;
int c;
int f;
int value;
struct NsEdge *next, *reverse;
};
// 最大流
class LMX_API MaxStream
{
public:
int N, s, t;
int maxStream;
int mode; // 0-dfs, 1-bfs
bool bCalculated, bFind;
NsEdge **ppEdge;
NsEdge **ppPath; // 记录路径
int *line, lineLen; // bfs
bool *used;
BaseAllocator *pAlloc;
public:
MaxStream(int iN, int i_s = 0, int i_t = 1, int imode = 0, BaseAllocator *palloc = &g_PojAlloc);
~MaxStream();
void AddEdge(int u, int v, int cuv, int cvu);
void Calculate();
private:
void dfs(int v);
void bfs();
};
}
lmx::MaxStream::MaxStream(int iN, int i_s, int i_t, int imode, BaseAllocator *palloc)
: N(iN), s(i_s), t(i_t), mode(imode), bCalculated(false), maxStream(0), pAlloc(palloc)
{
ppEdge = (NsEdge **)pAlloc->mallocv(N*sizeof(void*));
ppPath = (NsEdge **)pAlloc->mallocv(N*sizeof(void*));
line = (int*)pAlloc->mallocv(N*sizeof(int));
used = (bool*)pAlloc->mallocv(N*sizeof(bool));
}
lmx::MaxStream::~MaxStream()
{
NsEdge *p, *q;
for (int i = 0; i < N; i++)
{
p = ppEdge[i];
while (p != NULL)
{
q = p->next;
pAlloc->free(p);
p = q;
}
}
pAlloc->free(ppEdge);
pAlloc->free(ppPath);
pAlloc->free(line);
pAlloc->free(used);
}
void lmx::MaxStream::AddEdge(int u, int v, int cuv, int cvu)
{
NsEdge *puv = (NsEdge *)pAlloc->mallocv(sizeof(NsEdge));
NsEdge *pvu = (NsEdge *)pAlloc->mallocv(sizeof(NsEdge));
puv->c = cuv;
puv->v = v;
puv->reverse = pvu;
puv->next = ppEdge[u];
ppEdge[u] = puv;
pvu->c = cvu;
pvu->v = u;
pvu->reverse = puv;
pvu->next = ppEdge[v];
ppEdge[v] = pvu;
}
void lmx::MaxStream::Calculate()
{
int minf, temp;
NsEdge *p;
if (bCalculated)
return;
while(true)
{
lineLen = 0;
memset(ppPath, 0, N*sizeof(void*));
memset(used, 0, N);
if (mode == 0)
{
bFind = false;
dfs(s);
}
else if (mode == 1) bfs();
else return;
if (ppPath[t] == NULL)
break;
p = ppPath[t];
minf = p->reverse->c - p->reverse->f;
p = ppPath[p->v];
while (p != NULL)
{
temp = p->reverse->c - p->reverse->f;
if (minf > temp)
minf = temp;
p = ppPath[p->v];
}
maxStream += minf;
p = ppPath[t];
while (p != NULL)
{
p->f -= minf;
p->reverse->f += minf;
p = ppPath[p->v];
}
}
bCalculated = true;
}
void lmx::MaxStream::dfs(int v)
{
if (bFind) return;
if (v == t)
{
bFind = true;
return;
}
used[v] = true;
NsEdge *p = ppEdge[v];
while (p != NULL)
{
if (!bFind && !used[p->v] && p->f < p->c)
{
ppPath[p->v] = p->reverse;
dfs(p->v);
}
p = p->next;
}
}
void lmx::MaxStream::bfs()
{
lineLen = 1;
line[0] = s;
int f = 0, r, i;
NsEdge *p;
used[s] = true;
while(true)
{
r = lineLen;
for (i = f; i < lineLen; i++)
{
p = ppEdge[line[i]];
while (p != NULL)
{
if (!used[p->v] && p->f < p->c)
{
line[r] = p->v;
ppPath[p->v] = p->reverse;
if (p->v == t)
{
lineLen = r;
i = lineLen;
break;
}
used[p->v] = true;
}
p = p->next;
}
}
if (lineLen == r)
break;
f = lineLen;
lineLen = r;
}
}
int c[1024];
int main()
{
int n, m, s, x, y, d, i, sum;
scanf("%d", &n);
while (n--)
{
memset(c, 0, sizeof(c));
lmx::g_PojAlloc.reset();
scanf("%d%d", &m, &s);
lmx::MaxStream ms(m+2, 0, m+1);
for (i = 0; i < s; i++)
{
scanf("%d%d%d", &x, &y, &d);
c[x]++;
c[y]--;
if (d == 0)
ms.AddEdge(x, y, 1, 0);
}
for (i = 1; i <= m; i++)
if (c[i]&1)
break;
if (i <= m){
printf("impossible\n");
continue;
}
sum = 0;
for (i = 1; i <= m; i++)
if (c[i] > 0)
{
ms.AddEdge(0, i, c[i]/2, 0);
sum += c[i]/2;
}
else if (c[i] < 0)
{
ms.AddEdge(i, m+1, -c[i]/2, 0);
}
ms.Calculate();
if (ms.maxStream == sum)
printf("possible\n");
else
printf("impossible\n");
}
return 0;
}