ACM个人模板

  • 图论
    • 1最小生成树
      • 11 Kruskal
      • 12Prim
    • 2最短路径
      • 21 SPFA
      • 22Dijkstra
      • 23Floyd
    • 3网络流
      • 31Dinic
      • 32预流推进
      • 33Ford最裸的
      • 34费用流
    • 4二分图匹配
      • 41匈牙利算法
    • 5连通性问题
      • 51Tarjan
    • 6拓扑排序
    • 7A算法
  • 数据结构
    • 1线段树
      • 11单点更新
      • 11成段更新
    • 1字典树
  • 计算几何
    • 1求凸包
    • 2求直线相交
  • 字符串
    • 1KMP

1. 图论

1.1最小生成树

1.1.1 Kruskal

说明:并查集是优化过的

struct Edge  
{  
    int u, v, weight;  
};  

Edge edges[MAX_SIZE*MAX_SIZE];  
int nodeNum, edgeNum, pre[MAX_SIZE],  
    pos1[MAX_SIZE], pos2[MAX_SIZE];  
//pos1,pos2保存以连接的2个点。  

void FUset()
{
    for(int i=1;i<=500000;i++)
        pre[i]=i;
}

int Find(int x)
{
    return pre[x]==x?x:Find(pre[x]);
}

void Union(int x,int y)
{
    x=Find(x);
    y=Find(y);
    if(x==y)
        return ;
    pre[x]=y;
}


bool cmp(Edge a, Edge b)  
{  
    return a.weight < b.weight;  
}  

int Kruskal(int &buildEdgeNum)  
{  
    int i, u, v, maxWeight;  

    sort(edges, edges + edgeNum, cmp);  
    FUset();  
    buildEdgeNum = 0;  

    for(i = 0; i < edgeNum; i++){  
        u = Find(edges[i].u);  
        v = Find(edges[i].v);  
        if(u != v){  
            maxWeight = edges[i].weight;  
            Union(u, v);  
            pos1[buildEdgeNum] = edges[i].u;  
            pos2[buildEdgeNum] = edges[i].v;  
            buildEdgeNum++;  
        }  
        if(buildEdgeNum >= nodeNum - 1)  
            break;  
    }  

    return maxWeight;  
}  

1.1.2.Prim

int Prim(int start)  
{  
    int i, j, minEdge, res, v;  
    for(i = 0; i < nodeNum; i++)  
        lowCost[i] = graph[start][i];  

    lowCost[start] = -1;  

    res = 0;  
    for(i = 1; i < nodeNum; i++){  

        minEdge = INF;  

        for(j = 0; j < nodeNum; j++)  
            if(lowCost[j] != -1 && lowCost[j] < minEdge){  
                minEdge = lowCost[j];  
                v = j;  
            }  

        lowCost[v] = -1;  
        res += minEdge;  

        for(j = 0; j < nodeNum; j++)  
            if(lowCost[j] > graph[v][j])  
                lowCost[j] = graph[v][j];  
    }  

    return res;  
}  

1.2.最短路径

1.2.1. SPFA

//有负环返回 false, 否则返回 true  
bool spfa()  
{  
    int dist[MAX_SIZE], cnt[MAX_SIZE] = {0}, i, j, cur;  
    bool inQue[MAX_SIZE] = {0};  
    queue <int> que;  
//设0为起点  
    for(i = 1; i <= nodeNum; i++)  
        dist[i] = (1 == i? 0:INF);  

    que.push(1);  
    inQue[1] = true;  
    cnt[1]++;  

    while(!que.empty()){  
        cur = que.front();  
        inQue[cur] = false;  
        que.pop();  
        for(i = 1; i <= nodeNum; i++){  
            if(dist[i] > dist[cur] + graph[cur][i]){  
                dist[i] = dist[cur] + graph[cur][i];  
                if(cnt[i] > nodeNum-1)  
                    return false;  
                if(!inQue[i]){  
                    que.push(i);  
                    inQue[i] = true;  
                    cnt[i]++;  
                }  
            }  
        }  
    }  

    return true;  
}  

1.2.2.Dijkstra

void Dijkstra(int startPos, int dist[])  
{  
    int i, j, minPath, nextPos;  
    bool visited[MAX_SIZE] = {0};  

//initialize first vertex  
    visited[startPos] = true;  
    for(i = 1; i <= numOfVertex; i++){  
        if(graph[startPos][i] > 0 && !visited[i]){  
            dist[i] = graph[startPos][i];  
        }  
        else{  
            dist[i] = INF;  
        }  
    }  

    dist[startPos] = 0;  

    for(i = 2; i <= numOfVertex; i++){  
        minPath = INF;  
//find minPath  
        for(j = 1; j <= numOfVertex; j++){  
            if(dist[j] < minPath && !visited[j]){  
                    minPath = dist[j];  
                    startPos = j;  
            }  
        }  
//move  
        visited[startPos] = true;  

        for(j = 1; j <= numOfVertex; j++){  
            if(graph[startPos][j] > 0 && !visited[j] &&  
               minPath + graph[startPos][j] < dist[j] ){  
                    dist[j] = minPath + graph[startPos][j];  
               }  
        }  
    }  

}  

1.2.3.Floyd

double Floyd()  
{  
    int i, j, k;  
    for(k = 0; k < nodeNum; k++)  
        for(i = 0; i < nodeNum; i++)  
        for(j = 0; j < nodeNum; j++)  
            graph[i][j] = min(graph[i][j], max(graph[i][k], graph[k][j]));  

    return graph[0][1];  
}  

1.3.网络流

1.3.1.Dinic

说明:求最小点割集
1.有向图:把一个点拆成(i, i+N)2个点,之间容量为1。如果i, j2个点在原图中联通,则将i+N,j相连,容量为无穷大。然后求最小割,可见被最小割割到的都是容量是1的边,(如果割到一条INF,说明没有最小点割集。)而且那些边必将连着i,i+N,于是i就是被割的点。
2.无向图:把一个点拆成(i, i+N)2个点,之间容量为1。如果i, j2个点在原图中联通,则将i+N,j相连,容量为无穷大。则将j, i+N相连,容量为无穷大。以下如上。

class Dinic  
{  
public:  
    struct Edge  
    {  
        int v, w, next;  
    };  

    int cnt, head[MAX_N*2], dist[MAX_N*2], s, t;  
    Edge edges[MAX_N*MAX_N*2];  

    void init(int is, int it)  
    {  
        cnt = 0;  
        s = is, t = it;  
        memset(head, -1, sizeof(head));  
    }  

    void addEdge(int u, int v, int weight)  
    {  
        edges[cnt] = (Edge){v, weight, head[u]};  
        head[u] = cnt++;  
        edges[cnt] = (Edge){u, 0, head[v]};  
        head[v] = cnt++;  
    }  

    bool BFS()  
    {  
        int i, cur;  
        queue <int> que;  
        que.push(s);  
        memset(dist, -1, sizeof(dist));  
        dist[s] = 0;  
        while(!que.empty()){  
            cur = que.front();  
            que.pop();  
            for(i = head[cur]; i != -1; i = edges[i].next)  
                if(-1 == dist[edges[i].v] && edges[i].w){  
                    dist[edges[i].v] = dist[cur] + 1;  
                    que.push(edges[i].v);  
                }  
        }  

        return dist[t] != -1;  
    }  

    int DFS(int start, int curFlow)  
    {  
        if(start == t)  
            return curFlow;  
        int i, minFlow = 0, v, temp;  
        for(i = head[start]; i != -1; i = edges[i].next){  
            v = edges[i].v;  
            if(dist[start] == dist[v] - 1 && edges[i].w > 0){  
                temp = DFS(v, min(edges[i].w, curFlow));  
                edges[i].w -= temp;  
                edges[i^1].w += temp;  
                curFlow -= temp;  
                minFlow += temp;  
                if(0 == curFlow)  
                    break;  
            }  
        }  
        if(0 == minFlow)  
            dist[start] = -2;  
        return minFlow;  
    }  

    int maxFlow()  
    {  
        int res = 0;  
        while(BFS()){  
            res += DFS(s, INF);  
        }  
        return res;  
    }  
}G;  

bool edges[MAX_N][MAX_N];  
int edgeNum, nodeNum;  

int netFlow(int s, int t)  
{  
    G.init(s + nodeNum, t);  
    int i, j;  
    for(i = 0; i < nodeNum; i++){  
        G.addEdge(i, i + nodeNum, 1);  
        for(j = 0; j < nodeNum; j++)  
            if(edges[i][j])  
                G.addEdge(i + nodeNum, j, INF);  
    }  


    return G.maxFlow();  
}  
int S, T, N, mp[MAX_N][MAX_N], saveMap1[MAX_N], saveMap2[MAX_N];  

int buildGraph()  
{  
    int i, j;  
    Dinic G;  
    G.init(S+N, T);  
    for(i = 1; i <= N; i++)  
        G.addEdge(i, i + N, 1);  

    for(i = 1; i <= N; i++)  
        for(j = 1; j <= N; j++)  
            if(i != j && 1 == mp[i][j])  
                G.addEdge(i + N, j, INF);  

    return G.maxFlow();  
} 

1.3.2.预流推进

class Push_Relabel  
{  
public:  
    struct node  
    {  
        int x, h;  
        bool friend operator <(const node &a,const node &b)  
        {  
            return a.hstruct Edge  
    {  
        int v, weigt, next;  
    };  

    Edge edges[MAX_M*MAX_M];  
    int s, t, maxFlow, cnt,  
        head[MAX_M], H[MAX_M], EF[MAX_M];  
    priority_queue  que;  

    void init(int is, int it, int nodeNum)  
    {  
        memset(edges, 0, sizeof(edges));  
        memset(H, 0, sizeof(H));  
        memset(EF, 0, sizeof(EF));  
        memset(head, -1, sizeof(head));  
        maxFlow = 0;  
        cnt = 0;  
        s = is, t = it;  
        EF[s] = INF;  
        EF[t] = -INF;  
        H[s] = nodeNum;  
    }  

    void addEdge(int u, int v, int weight)  
    {  
        edges[cnt] = (Edge){v, weight, head[u]};  
        head[u] = cnt++;  
        edges[cnt] = (Edge){u, 0, head[v]};  
        head[v] = cnt++;  
    }  

    void Push(int cur)  
    {  
        int i, temp, v;  
        node tmp;  
        for(i = head[cur]; i != -1; i = edges[i].next){  
            v = edges[i].v;  
            temp = min(edges[i].weigt, EF[cur]);  
            if(temp > 0 &&(cur == s || 1==H[cur]-H[v])){  
                edges[i].weigt -= temp, edges[i^1].weigt += temp;  
                EF[cur] -= temp, EF[v] += temp;  
                if(v == t)  
                    maxFlow += temp;  
                if(v != s && v != t){  
                    tmp.x = v, tmp.h = H[v];  
                    que.push(tmp);  
                }  
            }  
        }  
    }  

    void Relabel(int cur)  
    {  
        node tmp;  
        if(cur != s && cur != t && EF[cur] > 0){  
            H[cur]++;  
            tmp.h = H[cur], tmp.x = cur;  
            que.push(tmp);  
        }  
    }  

    int ans()  
    {  
        node cur{s, H[s]};  
        que.push(cur);  
        while(!que.empty()){  
            cur = que.top();  
            que.pop();  
            Push(cur.x);  
            Relabel(cur.x);  
        }  
        return maxFlow;  
    }  
}G;  

int low[MAX_M][MAX_M], up[MAX_M][MAX_M], cnt[MAX_M],  
    row, col, s, t;  
bool ableSolve;  

void init()  
{  
    ableSolve = true;  
    s = row + col + 1, t = s + 1;  
    memset(cnt, 0, sizeof(cnt));  
    memset(low, 0, sizeof(low));  
    memset(up, INF, sizeof(up));  
    G.init(t + 1, t + 2, t + 2);  
}  

1.3.3.Ford(最裸的)

#include   
#include   
#include   
#include   
#include   
#include   
#include   

using namespace std;  

const int INF = 0x3f3f3f3f,  
          MAX_N = 109, MAX_M = 1008;  

int N, M, s, t;  
int capacity[MAX_N][MAX_N],  
    flow[MAX_N][MAX_N];  

void buildGraph()  
{  
    int i, j, key, keyNum,  
        pigNum[MAX_M], pre[MAX_M];  

    cin>>M>>N;  

    memset(pre, 0, sizeof(pre));  
    s = 0, t = N + 1;  

    for(i = 1; i <= M; i++)  
        cin>>pigNum[i];  

    for(i = 1; i <= N; i++){  
        cin>>keyNum;  
        for(j = 1; j <= keyNum; j++){  
            cin>>key;  
            if(0 == pre[key])  
                capacity[s][i] += pigNum[key];  
            else  
                capacity[ pre[key] ][i] = INF;  
            pre[key] = i;  
        }  
        cin>>capacity[i][t];  
    }  
}  

void Ford()  
{  
    int i, j, cur, save, preV[MAX_N],  
        flag[MAX_N], minFlow[MAX_N];  
    queue <int> que;  

    while(1){  

        memset(flag, -1, sizeof(flag));  
        memset(preV, -1, sizeof(preV));  
        while(!que.empty())  
            que.pop();  
        que.push(0);  
        minFlow[0] = INF;  
        flag[0] = 0;  

        while(!que.empty() && flag[t] == -1){  
            cur = que.front();  
            que.pop();  
            for(i = 0; i <= N+1; i++){  
                save = capacity[cur][i] - flow[cur][i];  
                if(-1 == flag[i] && save > 0){  
                    preV[i] = cur;  
                    minFlow[i] = min(minFlow[cur], save);  
                    flag[i] = 0;  
                    que.push(i);  
                }  
            }  
            flag[cur] = 1;  
        }  

        if(-1 == flag[t]) break;  

        for(i = preV[t], j = t; i != -1; j = i, i = preV[i]){  
            flow[i][j] += minFlow[t];  
            flow[j][i] = -flow[i][j];  
        }  
    }  

    for(i = 0, save = 0; i < t; i++)  
        save += flow[i][t];  

    cout<int main()  
{  
    //freopen("in.txt", "r", stdin);  

    buildGraph();  
    Ford();  

    return 0;  
}  

1.3.4.费用流

#include 
#include 
#include 
#include 
#include 

using namespace std;

const int INF = 0x3f3f3f3f,
          MAX_SIZE = 1000;

class AdjList
{
public:
    int *head, cnt;
    struct Edge
    {
        int cost, cap, v, next;
    }*edges;

    AdjList()
    {
        edges = new Edge[MAX_SIZE*MAX_SIZE];
        head = new int[MAX_SIZE];
        cnt = 0;
        memset(head, -1, sizeof(int)*MAX_SIZE);
    }

    ~AdjList()
    {
        delete[] edges;
        delete[] head;
    }
    void addEdge(int u, int v, int cap, int cost)
    {
        edges[cnt].v = v, edges[cnt].cap = cap,
        edges[cnt].cost = cost, edges[cnt].next = head[u];
        head[u] = cnt++;

        edges[cnt].v = u, edges[cnt].cap = 0,
        edges[cnt].cost = -cost, edges[cnt].next = head[v];
        head[v] = cnt++;
    }
};

class MinCost
{
public:
    AdjList G;
    int *dist, *pre, *path, s, t;
    MinCost()
    {
        dist = new int[MAX_SIZE];
        pre  = new int[MAX_SIZE];
        path = new int[MAX_SIZE];
    }

    ~MinCost()
    {
        delete[] dist;
        delete[] pre;
        delete[] path;
    }

    bool SPFA()
    {
        bool inQue[MAX_SIZE];
        queue <int> que;
        int cur, v, i;

        memset(dist, INF, sizeof(int)*MAX_SIZE);
        memset(inQue, 0, sizeof(inQue));
        memset(pre, -1, sizeof(int)*MAX_SIZE);

        dist[s] = 0;
        que.push(s);
        inQue[s] = true;

        while(!que.empty()){
            cur = que.front();
            que.pop();
            inQue[cur] = false;
            for(i = G.head[cur]; i != -1; i = G.edges[i].next){
                v = G.edges[i].v;
                if(G.edges[i].cap && dist[v] > dist[cur] + G.edges[i].cost){
                    dist[v] = dist[cur] + G.edges[i].cost;
                    pre[v] = cur;
                    path[v] = i;
                    if(!inQue[v]){
                        que.push(v);
                        inQue[v] = true;
                    }
                }
            }
        }
        return pre[t] != -1;
    }

    int ford_fulkerson(int &maxFlow)
    {
        int sum = 0, u, v, minFlow, i;
        maxFlow = 0;
        while(SPFA()){
            minFlow = INF;
            for(u = pre[t], v = t;  u != -1; v = u, u = pre[u]){
                i = path[v];
                minFlow = min(minFlow, G.edges[i].cap);
            }

            maxFlow += minFlow;
            for(u = pre[t], v = t;  u != -1; v = u, u = pre[u]){
                i = path[v];
                G.edges[i].cap -= minFlow;
                G.edges[i^1].cap += minFlow;
                sum += minFlow*G.edges[i].cost;
            }
        }
        return sum;
    }
};

const int MAX_N = 58;
int N, M, K,
    orders[MAX_N][MAX_N],
    supply[MAX_N][MAX_N],
    cost[MAX_N][MAX_N][MAX_N];

int getMinCost(int foodId)
{
    MinCost poj2516;
    int i, j, s, t, maxFlow, sumOrder, res;

    s = M+N+1, t = M+N+2;
    poj2516.s = s, poj2516.t = t;
    sumOrder = 0;

    for(i = 1; i <= M; i++)
        poj2516.G.addEdge(s, i, supply[i][foodId], 0);

    for(i = 1; i <= N; i++){
        poj2516.G.addEdge(i + M, t, orders[i][foodId], 0);
        sumOrder += orders[i][foodId];
    }

    for(i = 1; i <= M; i++)
        for(j = 1; j <= N; j++)
            poj2516.G.addEdge(i, j+M, INF, cost[foodId][j][i]);

    res = poj2516.ford_fulkerson(maxFlow);
    if(sumOrder != maxFlow)
        return -1;
    else
        return res;
}

int main()
{
    //freopen("in.txt", "r", stdin);

    int i, j, t, temp, sum;
    while(~scanf("%d%d%d", &N, &M, &K) && (N+M+K)){

        for(i = 1; i <= N; i++)
            for(j = 1; j <= K; j++)
                scanf("%d", &orders[i][j]);

        for(i = 1; i <= M; i++)
            for(j = 1; j <= K; j++)
                scanf("%d", &supply[i][j]);

        for(t = 1; t <= K; t++)
            for(i = 1; i <= N; i++)
                for(j = 1; j <= M; j++)
                    scanf("%d", &cost[t][i][j]);

        sum = 0;
        for(t = 1; t <= K; t++){
            temp = getMinCost(t);
            if(temp != -1)
                sum += temp;
            else{
                sum = -1;
                break;
            }
        }

        printf("%d\n", sum);
    }

    return 0;
}


1.4.二分图匹配

1.4.1.匈牙利算法


class maxMatch  
{  
public:  
    bool connected[MAX_SIZE][MAX_SIZE],  
         visited[MAX_SIZE];  
    int xMatch[MAX_SIZE], yMatch[MAX_SIZE],  
        xNum, yNum;  

    void init()  
    {  
        xNum = yNum = 0;  
        memset(connected, 0, sizeof(connected));  
        memset(xMatch, -1, sizeof(xMatch));  
        memset(yMatch, -1, sizeof(yMatch));  
    }  

    bool path(int u)  
    {  
        int v;  
        for(v = 1; v <= yNum; v++)  
        if(connected[u][v] && !visited[v]){  
            visited[v] = true;  
            if(-1 == yMatch[v] || path(yMatch[v])){  
                yMatch[v] = u;  
                xMatch[u] = v;  
                return true;  
            }  
        }  
        return false;  
    }  

    int getRes()  
    {  
        int i, res = 0;  
        for(i = 1; i <= xNum; i++)  
        if(-1 == xMatch[i]){  
            memset(visited, 0, sizeof(visited));  
            if(path(i))  
                res++;  
        }  
        return res;  
    }  

}G;

1.5.连通性问题

1.5.1.Tarjan

说明:给一个网络,节点与节点相连,让你求去掉某些节点能不能使得整个网络不联通

class Tarjan  
{  
public:  
    vector <int> edges[MAX_SIZE];  
    int low[MAX_SIZE], dfn[MAX_SIZE], root,  
        maxNode, subnetsNum[MAX_SIZE];  
    bool visited[MAX_SIZE], isNode[MAX_SIZE],  
         isSPF[MAX_SIZE], found;  

    void init()  
    {  
        int i;  
        for(i = 0; i < MAX_SIZE; i++)  
            edges[i].clear();  
        found = false;  
        memset(subnetsNum, 0, sizeof(subnetsNum));  
        memset(isNode, 0, sizeof(isNode));  
        memset(visited, 0, sizeof(visited));  
        memset(isSPF, 0, sizeof(isSPF));  
        maxNode = 0;  
    }  

    void addEdge(int u, int v)  
    {  
        edges[u].push_back(v);  
        edges[v].push_back(u);  
        maxNode = max(maxNode, max(u, v));  
        isNode[u] = isNode[v] = true;  
    }  

    void dfs(int u, int depth)  
    {  
        visited[u] = true;  
        low[u] = dfn[u] = depth;  
        int i, v;  
        for(i = 0; i < edges[u].size(); i++){  
            v = edges[u][i];  
            if(!visited[v]){  
                if(u == root)  
                    subnetsNum[root]++;  
                dfs(v, depth + 1);  
                if(u != root)  
                    low[u] = min(low[u], low[v]);  
                if(low[v] >= dfn[u] && u!= root){  
                    isSPF[u] = true;  
                    subnetsNum[u]++;  
                    found = true;  
                }  
            }  
            else  
                low[u] = min(low[u], dfn[v]);  
        }  
    }  

    void startDFS()  
    {  
        for(root = 1; root <= maxNode; root++)  
            if(isNode[root])  
                break;  
        dfs(root, 1);  
        if(subnetsNum[root] > 1){  
            isSPF[root] = true;  
            subnetsNum[root]--;  
            found = true;  
        }  
    }  
}G;  

1.6拓扑排序

void TopoSort()  
{  
    int i, cur;  
    queue <int> que;  
    for(i = 0; i < nodeNum; i++)  
        if(0 == cnt[i]){  
            que.push(i);  
            Ee[i] = 1;  
        }  

    while(!que.empty()){  
        cur = que.front();  
        que.pop();  
        for(i = 0; i < graph[cur].size(); i++){  
            if(0 == --cnt[graph[cur][i].v])  
                que.push(graph[cur][i].v);  
            Ee[graph[cur][i].v] =  
            max(Ee[cur] + graph[cur][i].weight, Ee[graph[cur][i].v]);  
        }  
    }  
}  

1.7.A*算法

//POJ2449
import java.util.*;

class Main {
    final static int MAX_SIZE = 1010;
    final static int INF = 0x3f3f3f3f;

    static class Node{
        public int v;
        public int weight;
    }

    static List Graph[] = new ArrayList[MAX_SIZE];
    static List reGraph[] = new ArrayList[MAX_SIZE];
    static int nodeNum;
    static int edgeNum;
    static int k;

    static int[] SPFA(int start, int end){
        int dist[] = new int[nodeNum+1];
        boolean inQue[] = new boolean[nodeNum+1];
        Queue que = new LinkedList();

        int i, cur;
        for (i = 0; i < nodeNum+1; i++){
            dist[i] = INF;
            inQue[i] = false;
        }
        dist[start] = 0;
        que.offer(start);
        inQue[start] = true;

        while (!que.isEmpty()) {
            cur = que.poll(); 
            inQue[cur] = false;
            Iterator it = reGraph[cur].iterator();
            while (it.hasNext()){
                Node node = it.next();
                int v = node.v;
                int weight = node.weight;

                if (dist[v] > dist[cur] + weight){
                    dist[v] = dist[cur] + weight;
                    if (!inQue[v]){
                        inQue[v] = true;
                        que.offer(v);
                    }
                }
            }
        }

        return dist;
    }

    static int AStar(int start, int end, int []H){
        class Point{
            public int id;
            public int h;
            public int g;
        }

        Comparator order = new Comparator(){
            public int compare(Point a, Point b){
                int fa = a.g + a.h;
                int fb = b.g + b.h;
                return fa>fb? 1:(fa==fb?0:-1);
            }
        };

        Queue que = new PriorityQueue(nodeNum, order);
        Point cur = new Point();
        cur.g = 0;
        cur.h = H[start];
        cur.id = start;

        que.offer(cur);
        int cnt = 0;

        while(!que.isEmpty()){
            cur = que.poll();

            if (cur.id == end){
                cnt++;

                if (cnt == k){
                    return cur.g + cur.h;
                }
            }

            Iterator it = Graph[cur.id].iterator();

            while(it.hasNext()){
                Node tmp = it.next();
                int v = tmp.v;
                int weight = tmp.weight;
                Point nextP = new Point();
                nextP.g = cur.g + weight;
                nextP.h = H[v];
                nextP.id = v;

                que.offer(nextP);
            }
        }

        return -1;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        nodeNum = in.nextInt();
        edgeNum = in.nextInt();

        int u, v, w, i;
        for (i = 1; i <= nodeNum; i++)
            Graph[i] = new ArrayList();

        for (i = 1; i <= nodeNum; i++)
            reGraph[i] = new ArrayList();

        for (i = 0; i < edgeNum; i++){
            u = in.nextInt();
            v = in.nextInt();
            w = in.nextInt();
            Node newNode = new Node();
            newNode.v = v;
            newNode.weight = w;
            Graph[u].add(newNode);
            //反向图
            Node newNodeForRe = new Node();
            newNodeForRe.v = u;
            newNodeForRe.weight = w;
            reGraph[v].add(newNodeForRe);
        }

        int start, end;
        start = in.nextInt();
        end = in.nextInt();
        k = in.nextInt();

        int dist[] = SPFA(end, start);
        if (start == end)
            k++;
        System.out.println(AStar(start, end, dist));

        in.close();
    }

}

2.数据结构

2.1线段树

2.1.1.单点更新

#define LC(t) t<<1  
#define RC(t) t<<1|1  

struct node  
{  
    int l, r, cnt;  
};  

node seTree[4*MAX_N];  

void build(int l, int r, int idx)  
{  
    seTree[idx].l = l;  
    seTree[idx].r = r;  
    seTree[idx].cnt = 0;  
    if(l == r)  
        return;  
    int mid = (l+r)>>1;  
    build(l, mid, LC(idx));  
    build(mid+1, r, RC(idx));  
}  

void add(int idx, int pos, int num)  
{  
    int l = seTree[idx].l,  
        r = seTree[idx].r;  

    if(l <= pos && r >= pos){  
        seTree[idx].cnt += num;  
        if(l == r)  
            return;  
        add(LC(idx), pos, num);  
        add(RC(idx), pos, num);  
    }  
}  

int query(int l, int r, int idx)  
{  
    int lSide = seTree[idx].l,  
        rSide = seTree[idx].r;  

    if(lSide == l && rSide == r)  
        return seTree[idx].cnt;  

    int mid = (lSide+rSide)>>1;  

    if(lSide <= l && mid >= r)  
        return query(l, r, LC(idx));  

    if(mid+1 <= l && rSide >= r)  
        return query(l, r, RC(idx));  

    if(lSide <= l && rSide >= r){  
        return query(l, mid, LC(idx)) +  
               query(mid+1, r, RC(idx));  
    }  
}  

2.1.1.成段更新


#include 
#include 

using namespace std;

const int MAX_N = 100100;
const int INF = 0x3f3f3f3f;

#define LC(t) t<<1
#define RC(t) t<<1|1

struct node
{
    int l, r;
    int mid()
    {
        return l+r >> 1;
    }
}seTree[4*MAX_N];

long long add[MAX_N<<2],sum[MAX_N<<2];

void build(int nd, int l, int r)
{
    seTree[nd].l = l;
    seTree[nd].r = r;
    sum[nd] = add[nd] = 0;
    if(l == r)
        return;
    int mid = seTree[nd].mid();
    build(LC(nd), l, mid);
    build(RC(nd), mid+1, r);
}

void pushDown(int nd, int len)
{
    if(!add[nd])
        return;
    add[LC(nd)] += add[nd];
    add[RC(nd)] += add[nd];
    sum[LC(nd)] += add[nd]*(len -(len>>1));
    sum[RC(nd)] += add[nd]*(len>>1);
    add[nd] = 0;
}

void pushUp(int nd)
{
    sum[nd] = sum[LC(nd)] + sum[RC(nd)];
}

void upDate(int nd, int l, int r,int ele)
{
    if(l == seTree[nd].l && r ==seTree[nd].r){
        sum[nd] += ele*(r-l+1);
        add[nd] += ele;
        return;
    }

    if(seTree[nd].l == seTree[nd].r)
        return;
    pushDown(nd, seTree[nd].r-seTree[nd].l+1);
    int mid = seTree[nd].mid();

    if(r <= mid)
        upDate(LC(nd), l, r, ele);
    else if(l > mid)
        upDate(RC(nd), l, r, ele);
    else{
        upDate(LC(nd), l, mid, ele);
        upDate(RC(nd), mid+1, r, ele);
    }
    pushUp(nd);
}

long long query(int nd, int l,int r)
{
    if(seTree[nd].l == l &&seTree[nd].r == r)
        return sum[nd];

    pushDown(nd, seTree[nd].r-seTree[nd].l+1);
    int mid = seTree[nd].mid();

    if(r <= mid)
        return query(LC(nd), l, r);
    if(l > mid)
        return query(RC(nd), l, r);
    return query(LC(nd), l, mid) +query(RC(nd), mid+1, r);
}

int main()
{
    //freopen("in.txt","r", stdin);

    int N, Q, i, ele, a, b, c;
    char ch;

    while(~scanf("%d%d", &N,&Q)){
        build(1, 1, N);

        for(i = 1; i <= N; i++){
            scanf("%d", &ele);
            upDate(1, i, i, ele);
        }

        for(i = 1; i <= Q; i++){
            scanf("\n%c %d %d",&ch, &a, &b);
            if(ch == 'C'){
                scanf("%d", &c);
                upDate(1, a, b, c);
            }
            else
                printf("%I64d\n",query(1, a, b));
        }
    }
    return 0;
}

2.1.字典树

#include   
#include   

using namespace std;  

const int MAX_N = 26;  
const int INF = 0x3f3f3f3f;  

struct node  
{  
    int cnt;  
    node* next[MAX_N];  
}heap[500000], root;  

int top;  
node *newNode()  
{  
    return &heap[top++];  
}  

void addNode(char *str)  
{  
    int len = strlen(str), i;  
    node *p = &root, *q;  

    for(i = 0; i < len; i++){  
        int key = str[i] - 'a';  
        if(p->next[key] == NULL){  
            q = newNode();  
            q->cnt = 1;  
            memset(q->next, 0, sizeof(q->next));  
            p->next[key] = q;  
            p = p->next[key];  
        }  
        else{  
            p = p->next[key];  
            p->cnt++;  
        }  
    }  
}  

int Find(char *str)  
{  
    node *p = &root;  
    int i, key;  
    for(i = 0; str[i]; i++){  
        key = str[i]-'a';  
        if(p->next[key] == NULL)  
            return 0;  
        p = p->next[key];  
    }  
    return p->cnt;  
}  

int main()  
{  
    //freopen("in.txt", "r", stdin);  

    char tmp[12];  
    while(gets(tmp) && tmp[0])  
        addNode(tmp);  

    while(~scanf("%s", tmp))  
        printf("%d\n", Find(tmp));  
    return 0;  
}  

3.计算几何

3.1.求凸包

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;


class Main {
    static final int MAX_SIZE = 1050;
    static final double INF = 1e40;
    static final double ESP = 1e-4;
    static int vertexNum;
    static double length;
    static List points = new ArrayList();
    static Point base;
    static Stack s;

    static double cross(Vector v1, Vector v2){
        return v1.x*v2.y - v2.x*v1.y;
    }

    static double pointDist(Point p1, Point p2){
        return Math.sqrt((p1.x-p2.x)*(p1.x-p2.x) +
                (p1.y-p2.y)*(p1.y-p2.y));
    }

    static void sortPoints(){
        Collections.sort(points, new Comparator(){
            @Override
            public int compare(Object arg0, Object arg1) {
                Point p1 = (Point)arg0;
                Point p2 = (Point)arg1;

                Vector v1 = new Vector();
                Vector v2 = new Vector();
                v1.setXY(base, p1);
                v2.setXY(p1, p2);
                double res = cross(v1, v2); 
                if(res > 0){
                    return -1;
                }else if(res == 0){
                    return (pointDist(p1, base) > 
                    pointDist(p2, base)? 1:-1);
                }else{
                    return 1;
                }

            }

        });
    }

    static void findConvexHull(){
        s = new Stack();
        s.push(points.get(0));
        s.push(points.get(1));
        s.push(points.get(2));

        for(int i = 3; i < vertexNum; i++){
            while(true){
                Point beJudged = s.pop();

                Point begin = s.peek();
                Vector v1 = new Vector(), v2 = new Vector();
                v1.setXY(begin, beJudged);
                v2.setXY(beJudged, points.get(i));

                if(cross(v1, v2)>=0){
                    s.push(beJudged);
                    break;
                }
            }
            s.push(points.get(i));
        }

    }

    public static void main (String args[]){

        Scanner in = new Scanner(System.in);
        double x, y;

        while(in.hasNext()){
            vertexNum = in.nextInt();
            length = in.nextDouble();
            int baseIdx = 0;
            points.removeAll(points);
            for(int i = 0; i < vertexNum; i++){
                x = in.nextDouble();
                y = in.nextDouble();
                Point p = new Point();
                p.setXY(x, y);
                points.add(p);
                if(points.get(baseIdx).y > y || 
                        points.get(baseIdx).y == y && 
                        points.get(baseIdx).x > x){
                    baseIdx = i;
                }
            }

            base = points.get(baseIdx);
            sortPoints();

            findConvexHull();


            double res = pointDist(base, s.peek());

            while(s.size() > 1){
                Point p = s.pop();
                res += pointDist(p, s.peek());
            }

            Point p = s.pop();
            res += pointDist(p, base);
            res += 2*Math.PI*length;

            System.out.println(Math.round(res));
        }
        in.close();
    }
}

class Point{
    public void setXY(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public double x, y;
}

class Vector{
    public void setXY(Point begin, Point end) {
        this.x = end.x-begin.x;
        this.y = end.y-begin.y;
    }

    public Vector reVector() {
        Vector v = new Vector();
        v.x = -x;
        v.y = -y;
        return v;
    }
    public double x, y;
}

3.2.求直线相交

import java.util.Scanner;

class Main {
    static final int MAX_SIZE = 110;
    static class Point{
        double x, y;
    }

    //输入向量(x1, y1), (x2, y2)
    static double crossProduct(double x1, double y1, double x2, double y2){
        return x1*y2- x2*y1;
    }       

    //parameter[] ={a, b, c} 直线:ax+by+c=0
    static void getLine(Point p1, Point p2, double[]parameter){

        parameter[0] = p1.y- p2.y;
        parameter[1] = p2.x -p1.x;
        parameter[2] = p1.x*p2.y - p2.x*p1.y;

    }

    public static void main (String args[]){

        Scanner in = new Scanner(System.in);
        int test = in.nextInt();
        Point []p = new Point[4];
        for (int i = 0; i < 4; i++){
            p[i] = new Point();
        }

        double [][] parameter = new double[2][3];
        double a1, a2, b1, b2, c1, c2;
        System.out.println("INTERSECTING LINES OUTPUT");
        while(test-- != 0){
            for (int i = 0; i < 4; i++){
                p[i].x = in.nextDouble();
                p[i].y = in.nextDouble();
            }


            getLine(p[0], p[1], parameter[0]);
            getLine(p[2], p[3], parameter[1]);

            a1 = parameter[0][0];
            b1 = parameter[0][1];
            c1 = parameter[0][2];
            a2 = parameter[1][0];
            b2 = parameter[1][1];
            c2 = parameter[1][2];

            double D1 = b2*(-c1)-b1*(-c2),
                    D2 = a1*(-c2)-a2*(-c1),
                    D = a1*b2 - a2*b1;

            if (D == 0 && D1 == 0 && D2 == 0){
                System.out.println("LINE");
            } else if (D == 0){
                System.out.println("NONE");
            } else {
                double x = D1/D;
                double y = D2/D;
                System.out.printf("POINT %.2f %.2f \n", x, y);
            }
        }
        System.out.println("END OF OUTPUT");
        in.close();
    }
}

4.字符串

4.1KMP


#include 
#include 
#include 

using namespace std;

const int MAX_N = 10100,
          INF = 0x3f3f3f3f;

int Next[MAX_N];
char pattern[MAX_N], match[1000100];

void getNext()
{
    int i, k;
    Next[0] = 0;
    for(i = 1;  pattern[i]; i++){
        k = Next[i-1];
        while(pattern[i] != pattern[k] && k > 0)
            k = Next[k-1];
        if(pattern[i] == pattern[k])
            Next[i] = k+1;
        else
            Next[i] = 0;
    }
}

int KMP()
{
    getNext();
    int i = 0, j = 0, cnt = 0;

    while(match[i]){
        while(j > 0 && pattern[j] != match[i])
            j = Next[j-1];
        if(pattern[j] == match[i])
            i++, j++;
        else
            i++;
        if(!pattern[j]){
            cnt++;
            j = Next[j-1];
        }
    }
    return cnt;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    int T;

    scanf("%d", &T);

    while(T--){

        scanf("%s%s", pattern, match);
        printf("%d\n", KMP());
    }

    return 0;
}

你可能感兴趣的:(acm)