记录练习poj题的一些痕迹和记忆一

/*


注:所有题意表达的可能不当,但最终意思差不多
    代码里面可能有繁琐重复的一些内存分配类之类的不用太在意,只是我个人的一个封装


1. poj3026 Borg Maze 最小生成树


题意: 在长方形格子地图上(w*h, w、h<=50),有起始点S,目标点A,空白点和障碍物#
从S出发最少需要多少步占领所有的A,上下左右移动为一步,不能移动到#点,S点及到A点
后可发出任意多的士兵。
其实就是求最小生成树,S、A当做节点


*/


#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;
}

/*


2. poj3691 DNA repair AC自动机


题意: DNA只有4种符号AGCT,给出一些子串,然后最后给一个串,求这个串不包含前面任
何一个子串,至少需要修改几个字符


AC自动机做动态规划,总是让人很难理解,不过我自己终于会写它了


*/


#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;
}

/*


3. poj2778 DNA Sequence AC自动机


题意: 和上题类似,DNA只有4种符号AGCT,给出一些子串,问n个字符长的串(4^n种)有多少个
串不包含前面任何的子串


AC自动机做动态规划,同样让人很难理解


*/

#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;
}

/*


4. poj2983 Is the Information Reliable? 差分最短路径


题意: 很多station南北向拉成直线,给出一些信息,判断是否正确
P A B X 表示A在B北方的X光年处
V A B   表示A在B北方至少1光年处,具体距离不清楚


一堆<=的条件,差分问题转换为求最短路径问题
需要注意的是BeelmanFord会超时,spfa不会


*/
#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;
}

/*


5. poj1637 Sightseeing tour 最大流


题意: 给出city里的结构描述:点和边,边可以是单向的和双向的。问是否满足遍历所有的边一次,
且起始点和结束点相同。


造图,计算最大流,造起始点和终点,双向的边任取一个方向加入图,对每个节点出入不平衡时,出的
多从起始点拉一些边到此点,入的多此点拉一些边到终点,计算出最大流和不平衡值比较,判断得出结果


理解挺费劲的


*/


#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;
}


你可能感兴趣的:(poj,cc++)